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 :

[Linux-Debian] Graphisme : besoin coup de main pour RangeCheckError incompréhensible [Lazarus]


Sujet :

Lazarus Pascal

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 930
    Points : 15 375
    Points
    15 375
    Par défaut [Linux-Debian] Graphisme : besoin coup de main pour RangeCheckError incompréhensible
    Bonsoir,

    J'ai récupéré sur la page https://forum.lazarus.freepascal.org...html#msg269273 une procédure "stand-alone" dont la partie centrale me joue des tours et me fait des misères.
    Au départ ça ressemble à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        Intf:=CY.CreateIntfImage;
        for i:=0 to pred(CY.Width) do
          for j:=0 to pred(CY.Height) do
            if Intf.TColors[i,j] > 0 then 
              Intf.TColors[i,j] := Intf.TColors[i,j] or $FF000000; // --> RangeCheckError
    et pour essayer de comprendre, j'ai bricolé les deux dernières lignes ci-dessus comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
            if Intf.TColors[i,j] > 0 then begin
            //Intf.TColors[i,j] := Intf.TColors[i,j] or $FF000000; // --> RangeCheckError
              total := Intf.TColors[i,j] or $FF000000;
              if total > 4294967294 then
                mmo.append(inttostr(Intf.TColors[i,j])+'  i='+inttostr(i)+'  j='+inttostr(j)+'  total='+inttostr(total));
              Intf.TColors[i,j] := total; // --> RangeCheckError
            end;
    Donc ma bidouille n'a rien changé, sauf que, pour la construire, cette bidouille, j'y suis allé petit à petit à coups d'ajouts de données dans le mémo, avec des begin end, de l'Application.ProcessMessages, l'introduction d'une variable intermédiaire bref j'ai réussi à faire fonctionner le bazar !
    Mais il aura suffi que j'enlève les tests et autres trucs inutiles (conservation de la variable intermédiaire) pour que ça ne fonctionne plus...

    Le gag c'est que si je commente la dernière ligne, je n'ai plus d'erreur et j'ai une image !, mon seul souci étant que je ne sais pas du tout si cette image que je vois est celle que je dois voir, ne comprenant pas trop à quoi sert la boucle for i for j.

    C'est pourquoi je compte un peu sur vous, avec les uses qui vont bien (y en a surement de trop) et le code de la procédure (qui aura besoin d'un TMemo name mmo) :
    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
    uses
      LclType, GraphType, LCLIntf,
      Classes, SysUtils, Forms, Controls, Graphics, Dialogs,
      FPWritePNG, FPWriteBMP, FPReadPNG, FPReadBMP,
      IntfGraphics, FPImage, FPCanvas, ExtDlgs, StdCtrls;
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      CY: TPortableNetworkGraphic;
      i, j: Integer;
      Intf: TLazIntfImage;
      total: uint;
    begin
      CY := TPortableNetworkGraphic.Create;
      CY.PixelFormat := pf32bit;
      CY.Canvas.Brush.FPColor:=colTransparent;
      CY.SetSize(300,300);
      CY.Canvas.FillRect(0,0,CY.Width-1,CY.Height-1);
      try
        CY.Canvas.Brush.Style := bsClear;
        CY.Canvas.Pen.FPColor := ColRed;
        CY.Canvas.Pen.Width := 10;
        CY.Canvas.Ellipse(10,10,100,100);
        with CY.Canvas.Font do begin
            FPColor := ColLime;
            PixelsPerInch := 300; /// always before height!
            Height := 32;
            ///Orientation := 1800;  /// Text is drawn upside down from right to left.
            Orientation := 0;  /// Text is drawn horizontally from left to right.
            Name := 'PlayBill';
            Quality := fqCleartypeNatural;
        end;
     
        CY.Canvas.Brush.Style := bsImage;
    //  CY.Canvas.TextOut(230,230,'EDGAR RULES!'); // if orientation = 1800
        CY.Canvas.TextOut(23,230,'EDGAR RULES!');  // if orientation = 0
     
        /// The plain bitmap has no Alpha, so we have to create an IntfImage, which passes the
        /// actual Canvas into an ABGR format that we control with TColors property.  After putting
        /// to all the painted things the $FF on the Alpha position, we pass it back to the CY.Canvas
     
        Intf:=CY.CreateIntfImage;
        for i:=0 to pred(CY.Width) do
          for j:=0 to pred(CY.Height) do
            if Intf.TColors[i,j] > 0 then begin
            //Intf.TColors[i,j] := Intf.TColors[i,j] or $FF000000; // --> RangeCheckError
              total := Intf.TColors[i,j] or $FF000000;
              if total > 4294967295 then
                mmo.append(inttostr(Intf.TColors[i,j])+'  i='+inttostr(i)+'  j='+inttostr(j)+'  tot='+inttostr(total));
    {          Intf.TColors[i,j] := total-1; // --> RangeCheckError  }
            end;                   // ce -1 ne change rien
        CY.LoadFromIntfImage(Intf);
     
        // scories de calcul
        // cardinal max = 4294967295
        //    $FF000000 = 4278190080
        //   4294967295
        // - 4278190080
        // =   16777215
     
        Canvas.Draw(50,50,CY); // dessine sur la fiche.
        CY.SaveToFile('./pruebaPNG.png');
      finally
        CY.Free;
        Intf.Free;
      end;
    end;
    Merci d'avance (il y a des noms bizarres dans ce code, ça ne gêne en rien)
    Nom : pruebaPNG.png
Affichages : 106
Taille : 3,5 Ko,

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 812
    Points : 13 524
    Points
    13 524
    Par défaut
    TColor est un entier signé et tu essayes de lui introduire une valeur supérieure à MaxInt. Traite cette valeur comme telle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Intf.TColors[i,j] := Intf.TColors[i,j] or integer($FF000000);
    ou TColor en entier non signé

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cardinal(Color) := Color or $FF000000;
    ou désactive le contrôle d'étendue

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    {$R-}
    Intf.TColors[i,j] := Intf.TColors[i,j] or $FF000000;
    {$R+}
    Citation Envoyé par Jipété Voir le message
    ne comprenant pas trop à quoi sert la boucle for i for j.
    Considérer le noir comme transparent et les autres comme entièrement opaques.

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 930
    Points : 15 375
    Points
    15 375
    Par défaut
    Bonjour, et un énorme merci pour cette chose qui ne m'est pas venue à l'esprit, même si je me doutais d'un coup pareil (mais je ne voyais pas comment le mettre en œuvre).

    J'ai pris la première proposition et, ma foi, ça le fait bien !
    Citation Envoyé par Andnotor Voir le message
    TColor est un entier signé et tu essayes de lui introduire une valeur supérieure à MaxInt. Traite cette valeur comme telle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Intf.TColors[i,j] := Intf.TColors[i,j] or integer($FF000000);
    Plus d'erreur.


    Citation Envoyé par Andnotor Voir le message
    Considérer le noir comme transparent et les autres comme entièrement opaques.
    Mais pourquoi une formule aussi compliquée, alors ?

    Et en plus, chez moi le noir est noir, pas transparent (mais la transparence c'est un boxon sans nom...)
    (hauteur un peu réduite)
    Nom : pruebaPNG.png
Affichages : 72
Taille : 3,3 Ko

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 812
    Points : 13 524
    Points
    13 524
    Par défaut
    Ce code n'est ni performant, ni très logique.

    1. Un png c'est un tableau RGB + un tableau alpha, ce n'est pas un tableau de quad. Travailler sur TColor oblige derrière un or sur ces deux tableaux (à la lecture et à l'écriture) alors que seule la couche alpha devrait être initialisée : perte de temps. De manière générale pour traiter une image complète, il est préférable de déterminer la profondeur des couleurs et d'utiliser Scanline.
    2. Le test devrait être if Intf.TColors[i,j] <> colTransparent then.
    3. C'est du tout ou rien (alpha = $00 ou $FF), pas d'anti alias. Même avec un rendu transparent il y aura une bordure colTransparent crénée autour du texte. Pour avoir quelque chose de correct il faut faire l'inverse : écrire sur la couche alpha (8 bits qui nous donnera un dégradé de gris = anti-alias) et remplir le RGB d'une couleur unie.
    4. {Form1.}Canvas.Draw est une fonction 24 bits, pas de notion de transparence, donc un fond colTransparent (!). Sous Windows on utiliserait AlphaBlend, sinon il faut prémultiplier image et fond : (foreground_color * alpha) + (background_color * (100% - alpha)) (avec foreground_color = scanline de l'image et background_color = scanline de la fiche).

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 930
    Points : 15 375
    Points
    15 375
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Ce code n'est ni performant, ni très logique.
    Ce n'est pas moi qui l'ai écrit,

    Citation Envoyé par Andnotor Voir le message
    1. {Form1.}Canvas.Draw est une fonction 24 bits, pas de notion de transparence, donc un fond colTransparent (!).
    Ah bon ben v'là aut' chose !
    Sous Linux à coups de Ctrl-Click pour remonter dans les sources en partant de Canvas.Draw, j'ai atterri sur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      TFPColor = record
        Red,Green,Blue,Alpha : word;
      end;
      PFPColor = ^TFPColor;
    Rien n'est simple, et je comprends mieux pourquoi des codes d'un OS ont du mal à passer sur l'autre OS...

    On n'est pas rendus, hein !

    Allez, j'y retourne : entre les pages web à 404 et les mises à jour des distros sans mises à jour des wikis, je te jure, c'est à pleurer,

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

Discussions similaires

  1. [AC-2010] Besoin coup de mains pour création des tables - Bulletin scolaire
    Par vincmori dans le forum Modélisation
    Réponses: 3
    Dernier message: 28/02/2011, 18h55
  2. Réponses: 7
    Dernier message: 23/12/2006, 13h43
  3. [RegEx] Besoin d'un coup de main pour écrire une regex
    Par gaboo_bl dans le forum Langage
    Réponses: 7
    Dernier message: 18/08/2006, 17h53
  4. besoin d'un coup de main pour une requête ;)
    Par Fabouney dans le forum Requêtes
    Réponses: 3
    Dernier message: 14/11/2005, 23h14

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