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 :

Traitement de plusieurs lignes de pixel avec scanline


Sujet :

Delphi

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Avril 2009
    Messages : 8
    Par défaut Traitement de plusieurs lignes de pixel avec scanline
    Bonjour,

    Dans le cadre d'un traitement d'image, je souhaite effectuer par exemple un flou gaussien. J'ai donc besoin d'accéder à plusieurs ligne de pixel à la fois, comment puis-je réaliser cela en utilisant la commande scanline?

    Voici mon code actuel qui me permet d'accéder aux lignes du bitmap une par une.
    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
     
    TYPE
      pRGBTripleArray = ^TRGBTripleArray;
      TRGBTripleArray = ARRAY[0..PixelCountMax-1] OF TRGBTriple;
     
    var
      BitmapOriginal, BitmapDeReference: TBitmap;
      Row:  pRGBTripleArray;
     
    FOR j := 0 TO BitmapDeReference.Height-1 DO
          begin
            Row := BitmapDeReference.Scanline[j];
            FOR i := 0 TO BitmapDeReference.Width-1 DO
            begin
              WITH Row[i] DO
              begin
                rgbtRed   := 255; // pixels jaunes
                rgbtGreen := 255;
                rgbtBlue  :=   0;
              end
            end
          end;
    Il me faudrais un truc du genre array of array of pRGBTripleArray mais ca ne marche pas.

    D'avance merci,

    Pascal.

  2. #2
    Membre chevronné
    Avatar de Whiler
    Homme Profil pro
    Inscrit en
    Avril 2002
    Messages
    298
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 298
    Par défaut
    Salut,

    Regarde comment ce code fonctionne.. cela répondra probablement à ta question...

    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
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    unit GBlur2;
     
    interface
     
    uses
      Windows, Graphics;
     
    type
      PRGBTriple = ^TRGBTriple;
      TRGBTriple = packed record
        b: byte; {easier to type than rgbtBlue}
        g: byte;
        r: byte;
      end;
      PRow = ^TRow;
      TRow = array[0..1000000] of TRGBTriple;
      PPRows = ^TPRows;
      TPRows = array[0..1000000] of PRow;
     
    const
      MaxKernelSize = 100;
     
    type
      TKernelSize = 1..MaxKernelSize;
      TKernel = record
        Size: TKernelSize;
        Weights: array[-MaxKernelSize..MaxKernelSize] of single;
      end;
      {the idea is that when using a TKernel you ignore the Weights except
      for Weights in the range -Size..Size.}
     
    procedure GBlur(theBitmap: TBitmap; radius: double);
     
    implementation
     
    uses
      SysUtils;
     
    procedure MakeGaussianKernel(var K: TKernel; radius: double; MaxData, DataGranularity: double);
    {makes K into a gaussian kernel with standard deviation = radius. For the current application
    you set MaxData = 255 and DataGranularity = 1. Now the procedure sets the value of K.Size so
    that when we use K we will ignore the Weights that are so small they can't possibly matter. (Small
    Size is good because the execution time is going to be propertional to K.Size.)}
    var
      j: integer;
      temp, delta: double;
      KernelSize: TKernelSize;
    begin
      for j := Low(K.Weights) to High(K.Weights) do
      begin
        temp := j / radius;
        K.Weights[j] := exp(-temp * temp / 2);
      end;
      {now divide by constant so sum(Weights) = 1:}
      temp := 0;
      for j := Low(K.Weights) to High(K.Weights) do
        temp := temp + K.Weights[j];
      for j := Low(K.Weights) to High(K.Weights) do
        K.Weights[j] := K.Weights[j] / temp;
      {now discard (or rather mark as ignorable by setting Size) the entries that are too small to matter.
      This is important, otherwise a blur with a small radius will take as long as with a large radius...}
      KernelSize := MaxKernelSize;
      delta := DataGranularity / (2 * MaxData);
      temp := 0;
      while (temp < delta) and (KernelSize > 1) do
      begin
        temp := temp + 2 * K.Weights[KernelSize];
        dec(KernelSize);
      end;
      K.Size := KernelSize;
      {now just to be correct go back and jiggle again so the sum of the entries we'll be using is exactly 1}
      temp := 0;
      for j := -K.Size to K.Size do
        temp := temp + K.Weights[j];
      for j := -K.Size to K.Size do
        K.Weights[j] := K.Weights[j] / temp;
    end;
     
    function TrimInt(Lower, Upper, theInteger: integer): integer;
    begin
      if (theInteger <= Upper) and (theInteger >= Lower) then
        result := theInteger
      else if theInteger > Upper then
        result := Upper
      else
        result := Lower;
    end;
     
    function TrimReal(Lower, Upper: integer; x: double): integer;
    begin
      if (x < upper) and (x >= lower) then
        result := trunc(x)
      else if x > Upper then
        result := Upper
      else
        result := Lower;
    end;
     
    procedure BlurRow(var theRow: array of TRGBTriple; K: TKernel; P: PRow);
    var
      j, n: integer;
      tr, tg, tb: double; {tempRed, etc}
      w: double;
    begin
      for j := 0 to High(theRow) do
      begin
        tb := 0;
        tg := 0;
        tr := 0;
        for n := -K.Size to K.Size do
        begin
          w := K.Weights[n];
          {the TrimInt keeps us from running off the edge of the row...}
          with theRow[TrimInt(0, High(theRow), j - n)] do
          begin
            tb := tb + w * b;
            tg := tg + w * g;
            tr := tr + w * r;
          end;
        end;
        with P[j] do
        begin
          b := TrimReal(0, 255, tb);
          g := TrimReal(0, 255, tg);
          r := TrimReal(0, 255, tr);
        end;
      end;
      Move(P[0], theRow[0], (High(theRow) + 1) * Sizeof(TRGBTriple));
    end;
     
    procedure GBlur(theBitmap: TBitmap; radius: double);
    var
      Row, Col: integer;
      theRows: PPRows;
      K: TKernel;
      ACol: PRow;
      P: PRow;
    begin
      if (theBitmap.HandleType <> bmDIB) or (theBitmap.PixelFormat <> pf24Bit) then
        raise exception.Create('GBlur only works for 24-bit bitmaps');
      MakeGaussianKernel(K, radius, 255, 1);
      GetMem(theRows, theBitmap.Height * SizeOf(PRow));
      GetMem(ACol, theBitmap.Height * SizeOf(TRGBTriple));
      {record the location of the bitmap data:}
      for Row := 0 to theBitmap.Height - 1 do
        theRows[Row] := theBitmap.Scanline[Row];
      {blur each row:}
      P := AllocMem(theBitmap.Width * SizeOf(TRGBTriple));
      for Row := 0 to theBitmap.Height - 1 do
        BlurRow(Slice(theRows[Row]^, theBitmap.Width), K, P);
      {now blur each column}
      ReAllocMem(P, theBitmap.Height * SizeOf(TRGBTriple));
      for Col := 0 to theBitmap.Width - 1 do
      begin
        {first read the column into a TRow:}
        for Row := 0 to theBitmap.Height - 1 do
          ACol[Row] := theRows[Row][Col];
        BlurRow(Slice(ACol^, theBitmap.Height), K, P);
        {now put that row, um, column back into the data:}
        for Row := 0 to theBitmap.Height - 1 do
          theRows[Row][Col] := ACol[Row];
      end;
      FreeMem(theRows);
      FreeMem(ACol);
      ReAllocMem(P, 0);
    end;
     
    end.

  3. #3
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 142
    Par défaut
    le code de Whiler semble très bien mais assez complexe pour un débutant

    En reprenant ton code, on peut dégager une pseudo-copie du Bitmap dans un Array

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    TYPE
      pRGBTripleArray = ^TRGBTripleArray;
      TRGBTripleArray = ARRAY[0..PixelCountMax-1] OF TRGBTriple;
      TRGBTripleMatrix = array of pRGBTripleArray;
     
    var
      BitmapOriginal, BitmapDeReference: TBitmap;
      BitmapMatrix:  TRGBTripleMatrix;
    begin
      SetLength(BitmapMatrix, BitmapDeReference.Height);
      FOR j := 0 TO BitmapDeReference.Height-1 DO
        BitmapMatrix[j] := BitmapDeReference.Scanline[j];
    BitmapMatrix contiendra l'ensemble des lignes, tu pourras travailler dessus comme source pour ton algorithme de Flou Gaussien

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    FOR j := 0 TO BitmapDeReference.Height-1 DO
      FOR i := 0 TO BitmapDeReference.Width-1 DO
        ... BitmapMatrix[i, j] ...
        ... BitmapMatrix[i + 1, j + 1] ...
    Pense qu'il existe aussi la propriété Pixels[], c'est un peu plus lent mais pour débuter, c'est déjà bien !
    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

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Avril 2009
    Messages : 8
    Par défaut Résolu!
    Merci, à vous deux.

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

Discussions similaires

  1. [AC-2010] Remplir plusieurs lignes d'enregistrement avec un formulaire
    Par scayhes dans le forum Access
    Réponses: 2
    Dernier message: 11/10/2014, 16h51
  2. Réponses: 7
    Dernier message: 29/11/2012, 13h03
  3. Faire le même traitement pour plusieurs lignes
    Par noraix dans le forum Débuter avec Java
    Réponses: 9
    Dernier message: 26/07/2011, 18h16
  4. Traitements de plusieurs lignes d'une rq
    Par radahm dans le forum SGBD
    Réponses: 6
    Dernier message: 11/08/2009, 12h09
  5. lire plusieurs lignes avec fgetc
    Par Mousk dans le forum C
    Réponses: 7
    Dernier message: 25/03/2006, 19h24

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