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 :

Index hors limites avec scanline


Sujet :

Langage Delphi

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 36
    Points : 31
    Points
    31
    Par défaut Index hors limites avec scanline
    Je développe un logiciel de type VNC très simple, il capture l'écran avec Bitblt et compare la nouvelle capture avec l'ancienne. J'utilise le code suivant pour la comparaison des bitmaps:
    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
     
    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');
     
        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
            If  CompareMem(@rowA[i], @rowB[i], SizeOf(TRGBTriple)) Then 
              Inc(Match)
              Else Inc(Differ)
          end;
        End
      End
    Les bitmaps ont toujours la même taille et au format 24bits. Le code semble fonctionner cependant de temps a autre j'ai des exceptions «Scan line index hors limite» ce qui me semble hautement improbable puisque les index sont toujours les mêmes il n'y a pas de raisons objectives pour qu'ils soient hors limites.
    Avez vous une idée de ce qui pourrait générer cette exception ?

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 534
    Points : 25 082
    Points
    25 082
    Par défaut
    Ton assert fonctionne ?
    Modifie ton code pour faire un test avec if et une exception dans le else, ça serait plus simple, les assert ne sont actives que pour le debug normalement !
    Tu ne les mettras plus dans une version de prod !

    Le reste semble assez cohérent

    hautement improbable
    Ce qui veut dire "rarement possible" mais possible quand même
    l'habituel différence entre la Théorie et la Pratique, le facteur Murphy !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Expert éminent sénior
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Points : 10 008
    Points
    10 008
    Par défaut
    Je me pose cette question: Et si les 2 bitmaps sont vides ?

    [Edit]
    Fausse bonne question, dans ce cas on n'entrerait pas dans les boucles.

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 36
    Points : 31
    Points
    31
    Par défaut
    ShaiLeTroll> merci je vais essayer
    Cl@udius> vides ? je teste le retour de Bitblt et les bitmaps sont créés de manière statique au début avec une taille fixe. N'est-ce pas suffisant pour s'assurer que quoi qu'il arrive ils ne seront pas considérés comme vides ?

    Cordialement

  5. #5
    Expert éminent sénior
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Points : 10 008
    Points
    10 008
    Par défaut
    Citation Envoyé par Lio590 Voir le message
    Cl@udius> vides ?
    L'edit de mon message précédent précise que c'était une fausse bonne question.

    J'ai pensé à cela car dans la fonction ScanLine, l'exception "Index hors limite" est levée si Row est < inf. à 0 ou sup. ou égal à bmHeight.

    @+

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 36
    Points : 31
    Points
    31
    Par défaut
    Cl@udius> J'ai ajouté le test "bitmap.empty ?" mais le probleme est toujours la.
    Je comprends quelles sont les conditions qui peuvent déclencher l'exception, le probleme c'est que dans la boucle l'index n'est jamais 0< ou > a BitmapA.height-1 / BitmapA.width-1 ou alors je ne comprend plus rien a Delphi.

  7. #7
    Expert éminent sénior
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Points : 10 008
    Points
    10 008
    Par défaut
    A part avec des bitmaps de tailles différentes, je ne vois pas pourquoi ScanLine lèverait une exception.

    D'où la question de Shai:
    Ton assert fonctionne ?
    Assure-toi qu'il soit bien pris en compte en ajoutant {$C+} juste devant, ou bien
    remplace le par un if OK else Exception, comme proposé par Shai.

    @+

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 36
    Points : 31
    Points
    31
    Par défaut
    J'ai testé l'assert il fonctionne correctement, j'ai fait des tests avec des valeurs statiques sur les dimensions de Bitmap et meme probleme. Je commence a penser que c'est un bug dans Delphi

  9. #9
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    pour ce genre de problème j'utilise toujours la même méthode

    1) ajoute un AllocConsole()
    2) dans ta boucle ajoute un WriteLn('j = ',j);

    quand ça plante, regarde la valeur de j dans la console.

    c'est plus efficace que de mettre un point d'arrêt conditionné

    et j'ajoute autant de WriteLn que nécessaire pour trouver ce qui ne va pas.
    exemple:
    Writeln('Bitmap = ', Bitmap.Width, 'x', Bitmap.Height);

    si tu veux la même chose dans un fichier log

    remplace AllocConsole() par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    AssignFile(Output, 'log.txt');
    Rewrite(output);
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 36
    Points : 31
    Points
    31
    Par défaut
    Paul> excellente idee, ca va permettre de confirmer ou pas le fait que les index restent dans les limites

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 745
    Points : 13 306
    Points
    13 306
    Par défaut
    Je ne sais pas si ça peut avoir une incidence, mais une chose qui n'est pas bonne est la déclaration :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TRGBTripleArray =  ARRAY[WORD] OF TRGBTriple;
    puisque tu admets qu'une ligne du bitmap fait 65536 pixels

    Dans pareil cas, on défini plutôt un tableau de taille inconnue (enfin 1 élément) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TRGBTripleArray =  ARRAY[0..0] OF TRGBTriple;
    De plus, dans un post précédent, tu disais travailler avec un thread. Es-tu sûr qu'il n'y a pas d'accès concurrent sur les mêmes bitmaps depuis la tâche principale ?

  12. #12
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 534
    Points : 25 082
    Points
    25 082
    Par défaut
    En plus 0..0 ça sera encore plus limitatif ! Non ?

    Mais effectivement, est-ce qu'il une vérification des bornes du tableau, cela laisse quand même 32000 pixels, vu que l'on est dans un mini-VNC, ça doit pas dépasser les 1920 x 1080 !
    Lorsque j'ai utilise des pointeurs sur tableau (seule méthode en D3), j'ai toujours indiqué la plus grande cardinalité, comme dans le code de la TList

    Lio590, à très juste titre, utilise la déclaration conseillé par nono04 dans son tutoriel
    Utilisation de la propriété TBitMap.ScanLine

    AllocConsole(), faudrait que j'essaye, moi j'utilise OutputDebugString pour cela !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 745
    Points : 13 306
    Points
    13 306
    Par défaut
    Ce n'est pas limitatif dans le sens où on travaille sur un pointeur. Peu importe la taille du tableau, on index à volonté. Il faut pour cela que ce pointeur pointe bien sur le premier élément du tableau, d'où le [0..0]. Ce n'est pas un tableau ouvert (ce qui donnerait un pointeur sur un pointeur de tableau )

    Je n'ai pas souvenir d'avoir eu un "Scan line index hors limite" (Des violations d'accès oui...) et la seule limite que je vois dans ce code est WORD.

  14. #14
    Membre confirmé
    Homme Profil pro
    Santé
    Inscrit en
    Septembre 2010
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Santé
    Secteur : Santé

    Informations forums :
    Inscription : Septembre 2010
    Messages : 290
    Points : 534
    Points
    534
    Par défaut
    Salut,

    La procedure est correcte (bien qu'on puisse l'optimiser) et je crois que Andnotor a mis le doigt sur le problème. Cela doit provenir d'un Thread qui change la hauteur d'un des bitmap.

    Pour vérifier, il suffit de passer les paramètres BitmapA et BitmapB par valeur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    PROCEDURE CompareBitmaps(BitmapA, BitmapB: TBitmap; VAR Total, Match, Differ: INTEGER);

  15. #15
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    la déclaration [0..0] ou [Word] ne change pas grand chose, de toute façon la taille est arbitraire et le range checking inapplicable.

    par contre TBitmap étant un objet, le paramètre const, var ou "par valeur" ne change strictement rien en Pascal...mise à part que la variable ne pourra pas être modifiée si elle est constante, alors que son contenu le pourra.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    procedure demo(const b: TBitmap);
    begin
      b := TBitmap.Create; // impossible car constant
      b.Height := 128; // autorisé !
    end;
    si le bitmap est modifié dans un Thread l'erreur est probablement là
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  16. #16
    Membre confirmé
    Homme Profil pro
    Santé
    Inscrit en
    Septembre 2010
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Santé
    Secteur : Santé

    Informations forums :
    Inscription : Septembre 2010
    Messages : 290
    Points : 534
    Points
    534
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    TBitmap étant un objet, le paramètre const, var ou "par valeur" ne change strictement rien en Pascal...mise à part que la variable ne pourra pas être modifiée si elle est constante, alors que son contenu le pourra.
    Oups! J'ai compris mon erreur. Merci pour la démo.


    Par contre, je n'utiliserais pas de type array :

    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
    Procedure CompareBitmaps(const BitmapA, BitmapB:  TBitmap; var Total, Match, Differ: Integer);
      var     ScanA, ScanB: pRGBQuad;
              i           : Integer;
    	begin
      BitmapA.PixelFormat := pf32bit;
      BitmapB.PixelFormat := pf32bit;
      Total               := BitmapA.width * BitmapA.height;
      Differ              := 0;
      ScanA               := BitmapA.ScanLine[BitmapA.Height-1];
      ScanB               := BitmapB.ScanLine[BitmapB.Height-1];
      for i := 1 to Total do begin
        if not CompareMem(ScanA,ScanB,4) then Inc(Differ);
        inc(ScanA);
        inc(ScanB);
      end;
      Match := Total-Differ;
    end;

  17. #17
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    c'est une autre façon de faire, mais attention à l'alignement des lignes ! sur un format pf24bits il peu y avoir un padding en fin de ligne pour avoir une largeur multiple de 4.

    mais l'erreur "Scan line index hors limite" vient de la propriété ScanLine[], pas de l'usage des pointeurs.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  18. #18
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 36
    Points : 31
    Points
    31
    Par défaut
    Bonjour,

    Tout d'abord merci a tous pour votre aide et suggestions.
    Je pense avoir trouvé d'où venait le problème. En fait l'intitulé de l'erreur «Index Scan Line hors limite» m'a conduit dans la mauvaise direction. En effet il était évident pour moi que le problème venait du seul endroit dans le code ou j'utilisais scanline. Que neni, il semble que bitblt utilise également scanline et c'est lui qui générait l'erreur !!
    Je l'ai compris lorsque j'ai recodé la procédure de comparaison des bitmaps avec getdibits et j'obtenais toujours la même erreur.

    Encore une fois merci a tous pour votre aide

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

Discussions similaires

  1. [SSRS][2k8] Index hors limites
    Par matb33 dans le forum SSRS
    Réponses: 5
    Dernier message: 12/05/2016, 12h34
  2. Index Hors limite sur Data Grid view.
    Par Seb1492 dans le forum C#
    Réponses: 3
    Dernier message: 04/08/2011, 09h05
  3. message d'erreur du a index hors limites
    Par kate59 dans le forum Développement 2D, 3D et Jeux
    Réponses: 4
    Dernier message: 19/04/2008, 20h01
  4. AdvOfficePager (TMS) index hors des limite?
    Par kheldoun ahmed dans le forum Delphi
    Réponses: 1
    Dernier message: 03/07/2007, 14h03
  5. Message d'erreur : Index XSQLDA hors limites
    Par loupiac dans le forum SQL
    Réponses: 2
    Dernier message: 31/12/2005, 09h08

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