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

Delphi Discussion :

Opération sur les pointeurs


Sujet :

Delphi

  1. #1
    Membre expérimenté

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2004
    Messages : 219
    Points : 1 655
    Points
    1 655
    Par défaut Opération sur les pointeurs
    Bonjour,

    Bien qu'ayant regardé la FAQ Delphi sur les pointeurs, je n'arrive pas à faire ce que je veux. En gros j'ai crée un buffer qui contient des éléments et je veux les parcourir. Voici les portions de code avec une instruction fausse mais qui montre ce que je veux 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
    15
    16
    17
    18
    19
    20
    21
    type 
       TPixel = array[0..2] of Byte;
       PTPixel = ^TPixel;
       TPixelData = array of array of TPixel;
     
    var
       myPixel : TPixel;
       PixelData : TPixelData;
       buffer, bufferIt : Pointer;
     
       GetMem(buffer, Img.Width * Img.Height * SizeOf(TPixel));
       glReadPixels(0, 0, Img.Width - 1, Img.Height - 1, GL_RGB, GL_UNSIGNED_BYTE, buffer);
       bufferIt := buffer;
       for i := 0 to Img.Width - 1 do
       begin
          for j := 0 to Img.Height - 1 do
          begin
             pixelData[i][j] := (TPixel (bufferIt^));
             bufferIt := bufferIt + 1;  // Op non applicable à ce type d'opérande.
          end;
       end;

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 587
    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 587
    Points : 25 263
    Points
    25 263
    Par défaut
    Essaye donc Inc pour passer au pointeur suivant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Inc(bufferIt, SizeOf(TPixel));

  3. #3
    Membre expérimenté

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2004
    Messages : 219
    Points : 1 655
    Points
    1 655
    Par défaut
    J'ai l'erreur Type ordinal requis.

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 587
    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 587
    Points : 25 263
    Points
    25 263
    Par défaut
    Inc fonctionne avec les PChar ou les pointeurs typés ... mais pas avec les pointeurs évidemment ...

    BufferIT c'est un pointeur mais sur quoi ?

    sinon reste

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bufferIt := Pointer(Integer(bufferIt) + 1);
    d'après quelques survols avec google, tu ne pourrais pas simplement ceci ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    type 
       TPixel = array[0..2] of Byte;
       PPixel = ^TPixel;
       TPixelData = array of array of TPixel;
       PPixelData = ^TPixelData;
     
    var
       myPixel : TPixel;
       PixelData : PPixelData;
     
       GetMem(PixelData, Img.Width * Img.Height * SizeOf(TPixel));
       glReadPixels(0, 0, Img.Width - 1, Img.Height - 1, GL_RGB, GL_UNSIGNED_BYTE, Pointer(PixelData));

  5. #5
    Membre expérimenté

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2004
    Messages : 219
    Points : 1 655
    Points
    1 655
    Par défaut
    Après l'exécution de l'instruction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glReadPixels(0, 0, Img.Width - 1, Img.Height - 1, GL_RGB, GL_UNSIGNED_BYTE, buffer);
    mon buffer va contenir des éléments (longueur * hauteur) TPixels (3 byte) qui représentent la surface de mon contexte opengl afin d'enregistrer cela dans une image.

    BufferIt c'était juste pour parcourir les éléments.

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 587
    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 587
    Points : 25 263
    Points
    25 263
    Par défaut
    Oui, c'est ce que j'ai cru compendre ... je dirais que tu pourrais même faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    type 
       TPixel = array[0..2] of Byte;
       PPixel = ^TPixel;
       TPixelData = array of array of TPixel;
     
    var
       myPixel : TPixel;
       PixelData : TPixelData;
     
       SetLength(PixelData, Img.Width);
       for i:= 0 to Img.Width - 1 do SetLength(PixelData[i], Img.Heigth);
     
       glReadPixels(0, 0, Img.Width - 1, Img.Height - 1, GL_RGB, GL_UNSIGNED_BYTE, @PixelData[0][0]);
    le .h (version pascal et version c) pourrait aider ... je n'ai pas opengl

  7. #7
    Membre expérimenté

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2004
    Messages : 219
    Points : 1 655
    Points
    1 655
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glReadPixels(0, 0, Img.Width - 1, Img.Height - 1, GL_RGB, GL_UNSIGNED_BYTE, Pointer(PixelData));
    =>Génère un EAccessViolation

    bufferIt := Pointer(Integer(bufferIt) + 1);
    => Génère une image bizarre.


    @PixelData[0][0] et @PixelData (que j'avais fait au début)
    => Génère un EAccessViolation

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 587
    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 587
    Points : 25 263
    Points
    25 263
    Par défaut
    as-tu fait le SetLength ? avec @PixelData[0][0] ?
    car c'est indispensable, c'est le getmem pour un tableau delphi ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
       SetLength(PixelData, Img.Width);
       for i:= 0 to Img.Width - 1 do SetLength(PixelData[i], Img.Heigth);
    sinon évidemment, c'est n'est +1 mais +3, pour le bon décalage mémoire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bufferIt := Pointer(Integer(bufferIt) + SizeOf(TPixel));

  9. #9
    Membre expérimenté

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2004
    Messages : 219
    Points : 1 655
    Points
    1 655
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bufferIt := Pointer(Integer(bufferIt) + SizeOf(TPixel));
    L'image est encore tordue et décalée mais on la distingue...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    type 
       TPixel = array[0..2] of Byte;
       PPixel = ^TPixel;
       TPixelData = array of array of TPixel;
       PPixelData = ^TPixelData;
     
    var
       myPixel : TPixel;
       PixelData : PPixelData;
     
       GetMem(PixelData, Img.Width * Img.Height * SizeOf(TPixel));
       glReadPixels(0, 0, Img.Width - 1, Img.Height - 1, GL_RGB, GL_UNSIGNED_BYTE, Pointer(PixelData));
    Ca passe mais c'est après pour récupérer un élément ca plante : c'est pas comme ca :

  10. #10
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Bien qu''ayant regardé la FAQ Delphi sur les pointeurs, je n''arrive pas à faire ce que je veux.
    Comme il s'agit de plus d'un traitement d'image j'aurais aussi regardé tout ce qui répond au mot-clef "Scanline" , propriété réputée permettre selon les cas d'utilisation d'obtenir des vitesses d'exec de 10 à 30 fois plus rapides que l'accès à la propriété Pixels[]

    Cela conduirait à remplacer les types suivants :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    type 
       TPixel = array[0..2] of Byte;
       PTPixel = ^TPixel;
       TPixelData = array of array of TPixel;
    par exemple par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    type
        pRGBArray  =  ^TRGBArray;
        TRGBArray  =  ARRAY[0..MaxPixelCount-1] of TRGBTriple; (TRGBTriple est déclaré dans l'unit windows.pas ligne 11914)
    Et qui conduit à un traitement ligne par ligne avec var maLigneSource : pRGBArray;

    Puis l'affectation par maLigneSource:= ImgSource.Picture.Bitmap.ScanLine[i]; ( avec i := 0 to ImgSource.Height - 1 )

    Puis si besoin est, action sur les R,G,B avec maLigneSource[j].rgbtRed:=function(R,G,B); ( avec j := 0 to ImgSource.Width - 1 )

    Ou copie en direct vers une ligne-cible avec ImgCible.Picture.Bitmap.ScanLine[i]:=maLigneSource ou:= ImgSource.Picture.Bitmap.ScanLine[i];

    En bref en utilisant Scanline on n'a même pas l'impression d'utiliser les pointeurs et en prime on a le bénef de la vitesse.

  11. #11
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 587
    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 587
    Points : 25 263
    Points
    25 263
    Par défaut
    Il utilise OpenGL, donc il doit respecter les types OpenGL, il est vrai qu'un packet record de trois bytes devraient être compatible avec ce TPixel ...

    maintenant nul part il y a mention de Bitmap, Picture ou Canvas ... mais d'une fonction OpenGL ?

  12. #12
    Membre expérimenté

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2004
    Messages : 219
    Points : 1 655
    Points
    1 655
    Par défaut
    Merci à tous les deux:

    J'ai refais ce matin avec le code suivant avec la finalité (L'image est ensuite redimentionnée avec filtre puis utilisée dans un rapport pour impression) et ca marche, même si ce n'est pas forcément le plus rapide c'est pratiquement immédiat alors qu'avant je pouvais attendre plus de 7 sec :

    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
    dataBuffer : array of byte;
     
       // Get the content of openGL context.
       ActivateRenderingContext(FDC, FRC);
       glReadBuffer(GL_BACK);
       setLength(DataBuffer, Ima.Width * Ima.Height * 3* SizeOf(Byte));
       glReadPixels(0, 0, Ima.Width - 1, Ima.Height - 1, GL_RGB, GL_UNSIGNED_BYTE, @dataBuffer[0]);
       DeactivateRenderingContext();
     
       // Copy gl content to image.
       for i := 0 to Ima.Width - 1 do
       begin
          for j := Ima.Height - 1 downto 0 do
          begin
             Ima.Canvas.Brush.Color := StrToIntDef('$' + IntToHex(DataBuffer[(j * (Ima.Width - 1) + i) * 3] +
                DataBuffer[(j * (Ima.Width - 1) + i) * 3 + 1] * 256 + DataBuffer[(j * (Ima.Width - 1) + i) * 3 + 2] * 65536, 6), clNone);
             rect.Left := i;
             rect.Right := i + 1;
             rect.Top := Ima.Height - 1 - j;
             rect.Bottom := rect.Top + 1;
             Ima.Canvas.FillRect(rect);
          end;
       end;
    PS : Avec bufferIt := Pointer(Integer(bufferIt) + SizeOf(TPixel)); ca doit marcher, c'est juste que je m'étais planté dans mes conditions de boucles ou bien quelque chose dans le genre...

    EDIT : Scanline semble intéressant, il faut juste que je regarde vraiment comment ca marche et si c'est compatible avec la fonction opengl.

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

Discussions similaires

  1. Opérations sur les matrices...
    Par aokiseiichiro dans le forum C
    Réponses: 32
    Dernier message: 28/07/2005, 17h10
  2. questions sur les pointeurs
    Par Hyoga dans le forum C++
    Réponses: 17
    Dernier message: 08/01/2005, 23h25
  3. opérations sur les bits d'un byte
    Par petitours dans le forum C++Builder
    Réponses: 4
    Dernier message: 10/02/2004, 20h42
  4. Pb de débutant sur les pointeurs!!!
    Par benji17c dans le forum C
    Réponses: 6
    Dernier message: 30/09/2003, 17h50
  5. opérations sur les dates
    Par coucoucmoi dans le forum Débuter
    Réponses: 2
    Dernier message: 12/08/2003, 11h45

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