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 :

Comportement différent du TBitmap selon qu'on utilise LoadFromFile ou FillRect / TextOut [Lazarus]


Sujet :

Lazarus Pascal

Vue hybride

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut Comportement différent du TBitmap selon qu'on utilise LoadFromFile ou FillRect / TextOut
    Bonsoir,

    Y avait longtemps...

    J'ai cru devenir fou cet aprème : une petite fonction qui mixe deux fichiers bitmap en un seul, qui fonctionne très bien en test et qui se vautre complètement une fois copiée/collée dans un gros projet, sans lui changer une virgule !
    Des heures que je suis dessus...

    • En test j'ouvre deux fichiers bitmap avec LoadFromFile, et je les passe à la fonction, le résultat est impec, il n'y a vraiment rien à dire.
    • En prod je remplis mes deux bitmaps par code (voir + bas), l'un avec une couleur unie, l'autre avec du texte et je me retrouve avec les traits verticaux caractéristiques des problèmes de scanline (oui, la fonction l'utilise pour combiner les deux bitmaps).



    Ça c'est parfait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      Bmp4Text.LoadFromFile(PChar(ExtractFilePath(Application.ExeName)) + 'Text.bmp');
      Bmp4Fond.LoadFromFile(PChar(ExtractFilePath(Application.ExeName)) + 'Fond.bmp');
      //WriteTextOnBitmap; // travaille avec Bmp4Text
      //DrawColorOnBitmap; // travaille avec Bmp4Fond -- fond bleu au lancement
      MixBmp := CombineBitmaps(Bmp4Text, Bmp4Fond);
      img4Affichage.Canvas.Draw(0, 0, MixBmp);
    Et ça c'est la cata :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      //Bmp4Text.LoadFromFile(PChar(ExtractFilePath(Application.ExeName)) + 'Text.bmp');
      //Bmp4Fond.LoadFromFile(PChar(ExtractFilePath(Application.ExeName)) + 'Fond.bmp');
      WriteTextOnBitmap; // travaille avec Bmp4Text
      DrawColorOnBitmap; // travaille avec Bmp4Fond -- fond bleu au lancement
      MixBmp := CombineBitmaps(Bmp4Text, Bmp4Fond);
      img4Affichage.Canvas.Draw(0, 0, MixBmp);
    Résultats (image réduite de moitié) :
    Nom : compar_bmps2.png
Affichages : 346
Taille : 3,5 Ko

    Je précise à tout hasard que la création des 2 bitmaps inclut la séquence PixelFormat := pf24bit;, et que Width et Height sont forcés aux valeurs du TImage d'affichage.

    Le remplissage des bitmaps :
    pour la couleur unie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      with Bmp4Fond.Canvas do begin
        Brush.Color := DirectColor; // un truc à moi, qui peut varier
        FillRect(ClipRect);
      end;
    C'est tout ! Et pour le texte :
    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
      Bmp4Text.Height := Bmp4Fond.Height;
      Bmp4Text.Width  := Bmp4Fond.Width;
      with Bmp4Text.Canvas do begin
        Brush.Color := clWhite; // fond blanc
        FillRect(ClipRect);
        with Font do begin
          Name   := FontName;
          Size   := FontSize;
          Style  := FontStyle;
          Color  := AlternColor; // un truc à moi, qui peut varier
        end;
      end;
      with Bmp4Text.Canvas do TextOut(
        10, // pas complètement collé à gauche
        (Bmp4Fond.Height - Bmp4Text.Canvas.TextHeight('Hp')) div 2, // au milieu
        ledSaisieTexte4Contrast.Text);
    Comment me sortir de ce pétrin à part en enregistrant WriteText et DrawColor pour ensuite les recharger ?

  2. #2
    Membre Expert
    Avatar de supersnail
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 719
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 719
    Par défaut
    Bonjour,

    Serait-il possible de voir le code de CombineBitmaps ?

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

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 931
    Billets dans le blog
    6
    Par défaut
    Que donne l'affichage dans des TImage de ces Bitmaps ainsi produits ?
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut
    Citation Envoyé par supersnail Voir le message
    Bonjour,

    Serait-il possible de voir le code de CombineBitmaps ?
    Mais bien sûr :
    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
    function TfrmContrast.CombineBitmaps(aTextBmp, aFondBmp: TBitmap): TBitmap;
    const
      Seuil = 96; // au plus on va vers zéro au plus le texte est pur
      // mais ne pas descendre trop bas non plus, car ça devient moche -- 96 ça a l'air bien
    var
      CT    : pRGBTripleArray;  // Couleur pixel Texte
      CF    : pRGBTripleArray;  // Couleur pixel Fond
      x, y  : integer;
      MaxX, MaxY : integer;
    begin
      //Force les images en 24 bits // vient de Delphi
      // pas sûr qu'en Lazarus/Gtk2 il n'y ait pas des blagues...
      aTextBmp.PixelFormat := pf24bit;
      aFondBmp.PixelFormat := pf24bit;
     
      Result := TBitmap.Create; //Crée l'image résultante
      Result.Assign(aFondBmp); //Assigne l'image de fond à l'image résultante
     
      //Boucle maximum sur les plus petites Largeur/Hauteur
      MaxX := Min(aTextBmp.Width,  aFondBmp.Width);
      MaxY := Min(aTextBmp.Height, aFondBmp.Height);
     
      aTextBmp.BeginUpdate();
      Result.BeginUpdate();
      for y := 0 to MaxY-1 do begin // parcourir les lignes une par une
        CT := pRGBTripleArray(aTextBmp.RawImage.GetLineStart(y));
        CF := pRGBTripleArray(Result.RawImage.GetLineStart(y));
        for x := 0 to MaxX-1 do begin // parcourir les pixels de la ligne en cours, un par un
          // si pixel différent de blanc, remplace fond par texte
          //if ((CT[x].rgbtRed < 255) and (CT[x].rgbtGreen < 255) and (CT[x].rgbtBlue < 255)) then begin
          // ligne dessus ne fonctionne pas bien, celle dessous avec les "or" fonctionne bien, bizarre
          if ((CT[x].rgbtRed   < Seuil)
          or  (CT[x].rgbtGreen < Seuil)
          or  (CT[x].rgbtBlue  < Seuil)) then
          begin
            CF[x].rgbtRed   := CT[x].rgbtRed;
            CF[x].rgbtGreen := CT[x].rgbtGreen;
            CF[x].rgbtBlue  := CT[x].rgbtBlue;
          end;
        end;
      end;
      aTextBmp.EndUpdate();
      Result.EndUpdate();
    end;
    Ce truc vient de cette discussion, un peu adapté : http://www.developpez.net/forums/d66...t-bmp-jpg-png/

    Citation Envoyé par tourlourou Voir le message
    Que donne l'affichage dans des TImage de ces Bitmaps ainsi produits ?
    Que du bon : je ne te donne que le bmp4Text (parce qu'il y a du texte, même s'il est jaune sur blanc donc pas très lisible), le bmp4Fond est un bête rectangle bleu Navy :
    Nom : bmp4Text.png
Affichages : 284
Taille : 2,8 Ko

    EDIT :

    Bon, pour que ça fonctionne, je fais ainsi, avec 2 TMemoryStream :
    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
    var
      MixBmp: TBitmap;
      msF, msT: TMemoryStream;
    begin
      msF:= TMemoryStream.Create;
      msT:= TMemoryStream.Create;
      WriteTextOnBitmap; // travaille avec Bmp4Text
      DrawColorOnBitmap; // travaille avec Bmp4Fond -- fond bleu au lancement
      Bmp4Text.SaveToStream(msT);
      Bmp4Fond.SaveToStream(msF);
      msT.Position:=0; msF.Position:=0;
      Bmp4Text.LoadFromStream(msT, msT.Size);
      Bmp4Fond.LoadFromStream(msF, msF.Size);
      MixBmp := CombineBitmaps(Bmp4Text, Bmp4Fond);
      img4Contrast.Canvas.Draw(0, 0, MixBmp);
    Pourquoi faire simple quand on peut faire compliqué, hein, c'est bien connu

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

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

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Billets dans le blog
    2
    Par défaut
    Salut, bizarre ton truc on dirait que ton bitmap de sortie est à pixelformat := pf32bits Cela pourrai expliquer ton soucis. Essayes de le forcer à 24bits.
    ou sinon je pensais au padding de fin de ligne des Bitmaps passé en entrés (mais c'est pas ça à mon avis).

    //if ((CT[x].rgbtRed < 255) and (CT[x].rgbtGreen < 255) and (CT[x].rgbtBlue < 255)) then begin
    // ligne dessus ne fonctionne pas bien, celle dessous avec les "or" fonctionne bien, bizarre
    C'est normal avec le Or que cela fonctionne mieux (Example Bleu = R:0, G:0, B:255) avec "And" la condition n'est pas rempli B=255. Avec And il faut que toutes les composantes soient inférieur à 255.
    Avec le Or seulement si une des composante est inferieure à 255.

    BeginUpdate(); EndUpdate; tu peux les virer servent à rien avec scanline ; c'est surtout à utiliser, pour englober les appels aux fonctions de Canvas, si mes souvenirs sont bons

    Essayes ça pour voir. Plus bonus une tchite fonction de mix

    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
     
    function ClampByte(const Value: Integer): Byte;
    begin
     if Value > 255 then
       Result := 255
     else
     if Value < 0 then
       Result := 0
     else
       Result := Value;
    end;
     
    function ColorMix(AColor,BColor:TRGBTriple;const Percent : single):TRGBTriple;
    var
      pct:single;
    begin
         pct:=100-Percent;
    //     result.alpha := AColor.alpha;
         result.rgbtRed  := ClampByte(round( ((AColor.rgbtRed/100)  *pct) + ((BColor.rgbtRed/100)  *Percent) ));
         result.rgbtGreen := ClampByte(round( ((AColor.rgbtGreen/100)*pct) + ((BColor.rgbtGreen/100)*Percent) ));
         result.rgbtblue  := ClampByte(round( ((AColor.rgbtblue/100) *pct) + ((BColor.rgbtBlue/100) *Percent) ));
    end;
     
    function TfrmContrast.CombineBitmaps(aTextBmp, aFondBmp: TBitmap): TBitmap;
    const
     SeuilR := 255;
     SeuilG := 255;
     SeuilB := 255;
    var
      CT    : pRGBTripleArray;  // Couleur pixel Texte
      CF, CR    : pRGBTripleArray;  // Couleur pixel Fond
      x, y  : integer;
      MaxX, MaxY : integer;
      TmpBmp : TBitmap;
    begin
     
      aTextBmp.PixelFormat := pf24bit;
      aFondBmp.PixelFormat := pf24bit;
     
      //Boucle maximum sur les plus petites Largeur/Hauteur
      MaxX := Min(aTextBmp.Width,  aFondBmp.Width);
      MaxY := Min(aTextBmp.Height, aFondBmp.Height);
     
      TmpBmp:= TBitmap.Create; //Crée l'image résultante
      TmpBmp.SetSize(MaxX, MaxY);
      tmpBmp.PixelFormat := pf24bits;
     
      for y := 0 to MaxY-1 do begin // parcourir les lignes une par une
        CT := pRGBTripleArray(aTextBmp.RawImage.GetLineStart(y));
        CF := pRGBTripleArray(aFondBmp.RawImage.GetLineStart(y));
        CR := pRGBTripleArray(TmpBmp.RawImage.GetLineStart(y));
        for x := 0 to MaxX-1 do 
        begin      
          if ((CT[x].rgbtRed   = SeuilR)
          and  (CT[x].rgbtGreen = SeuilG)
          and  (CT[x].rgbtBlue  = SeuilB)) then
            CR[X] := CF[X]
         else     
            CR[x] := ColorMix(CF[X], CT[X],100);
        end;
      end;
      Result:= TmpBmp;
    end;
    EDIT : Sinon a la place de
    if ((CT[x].rgbtRed = SeuilR) and (CT[x].rgbtGreen = SeuilG) and (CT[x].rgbtBlue = SeuilB)) then tu pourrais calculer l'intensité moyenne if ((CT[x].rgbtRed+CT[x].rgbtGreen+CT[x].rgbtBlue) div 3) < Seuil then
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut
    Citation Envoyé par BeanzMaster Voir le message
    Salut, bizarre ton truc on dirait que ton bitmap de sortie est à pixelformat := pf32bits Cela pourrait expliquer ton souci. Essaye de le forcer à 24bits.
    C'est bien ce que je me suis dit aussi. C'est forcé à 24, je l'ai écrit dans le 1er post.

    Citation Envoyé par BeanzMaster Voir le message
    C'est normal avec le Or que cela fonctionne mieux (Example Bleu = R:0, G:0, B:255) avec "And" la condition n'est pas rempli B=255. Avec And il faut que toutes les composantes soient inférieur à 255.
    Avec le Or seulement si une des composante est inferieure à 255.
    Rien compris et pas d'accord ! Je veux virer le blanc autour du texte pour ne recopier que le texte depuis le bitmap "texte" vers le bitmap destination, donc tout ce qui est à 255 ET 255 ET 255 ne doit pas être copié. Et si je le fais avec des and ça fonctionne mal, j'y comprends rien, mais c'est pas grave, il y a plein d'autres choses qui fonctionnent mal sans bonnes raisons...

    Citation Envoyé par BeanzMaster Voir le message
    BeginUpdate(); EndUpdate; tu peux les virer servent à rien avec scanline ; c'est surtout à utiliser, pour englober les appels aux fonctions de Canvas, si mes souvenirs sont bons
    Flemme de faire le test ce soir mais il me semble bien qu'il les faut, c'est une des premières choses que j'ai apprises quand j'ai commencé à jouer avec Scanline.

    Bon, allez, pour ce soir j'en ai marre.

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

Discussions similaires

  1. SimUnlockPhone comportement différent selon les téléphones
    Par bobby51 dans le forum Windows Mobile
    Réponses: 0
    Dernier message: 29/04/2011, 10h43
  2. Comportement différent de cos() selon contexte de l'appel
    Par dreydrey dans le forum Bibliothèque standard
    Réponses: 3
    Dernier message: 10/01/2011, 17h01
  3. Réponses: 7
    Dernier message: 15/02/2010, 21h52
  4. Comportement différent selon le lanceur
    Par michelcky dans le forum GTK+ avec C & C++
    Réponses: 1
    Dernier message: 03/10/2008, 19h03
  5. Comportement différent selon Mode Execution
    Par MarronSuisse dans le forum C
    Réponses: 7
    Dernier message: 14/04/2008, 12h52

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