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

Composants FMX Delphi Discussion :

Visualisation d'une image


Sujet :

Composants FMX Delphi

  1. #1
    Membre du Club

    Profil pro
    senior scientist
    Inscrit en
    Mai 2003
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : senior scientist

    Informations forums :
    Inscription : Mai 2003
    Messages : 79
    Points : 67
    Points
    67
    Billets dans le blog
    1
    Par défaut Visualisation d'une image
    Bonsoir,

    Je dispose de tableaux d'octets qui représentent des images en niveaux de gris.
    Je voudrais les montrer dans un TImage sous FMX.

    Je n'ai pas trouvé le moyen de modifier le format initial RGBA obtenu (obligatoirement ?) à la création du bitmap (pour le transformer en format L par exemple).
    Ceci même en utilisant TBitmap.Map car le paramètre de format (TPixelFormat) y est en lecture seule.

    Une solution possible pourrait être de charger les octets R,G,B à la même valeur et A à $FF, pixel par pixel, mais sans doute au détriment de l'efficacité (en temps d'exécution et taille du bitmap).

    Y a-t-il une solution plus simple pour ce problème élémentaire ?

    Merci d'avance,
    alx

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 029
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 029
    Points : 40 927
    Points
    40 927
    Billets dans le blog
    62
    Par défaut
    On pourrait avoir une image d'essai ?
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  3. #3
    Membre du Club

    Profil pro
    senior scientist
    Inscrit en
    Mai 2003
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : senior scientist

    Informations forums :
    Inscription : Mai 2003
    Messages : 79
    Points : 67
    Points
    67
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    On pourrait avoir une image d'essai ?
    Mais certainement :
    Le zip contient un simple tableau d'octets de dimension 455x436, contenant l'une des couleurs de l'image test bien connue suivante, ici en PNG monochrome (R=G=B).

    Nom : Original-test-image-Lena.png
Affichages : 106
Taille : 175,0 Ko
    Fichiers attachés Fichiers attachés

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

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 853
    Points : 11 285
    Points
    11 285
    Billets dans le blog
    6
    Par défaut
    Bonjour,
    Si tes images utilisent la palette de 256 niveaux de gris, ont toutes la même taille et que celle-ci ne pose pas de problème de padding par rapport au stockage dans un fichier bitmap, il suffit pê de copier dans un stream l'entête d'un fichier bitmap valide de ce type, puis ton tableau d'octets, avant de faire un LoadFromStream ?
    Mais ça fait beaucoup de si...
    Sinon, même type de solution en construisant l'en-tête et en ajoutant le padding éventuellement nécessaire.
    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 !

  5. #5
    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 430
    Points
    28 430
    Par défaut
    une solution assez simple pour gérer un tableau de pixel est de produire un Bitmap dans un Stream

    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
     
    type
      TRGBQuad = packed record
        rgbBlue: Byte;
        rgbGreen: Byte;
        rgbRed: Byte;
        rgbReserved: Byte;
      end;
     
      TBitmapFileHeader = packed record
        bfType: Word;
        bfSize: DWORD;
        bfReserved1: Word;
        bfReserved2: Word;
        bfOffBits: DWORD;
      end;
     
      TBitmapInfoHeader = packed record
        biSize: DWORD;
        biWidth: Longint;
        biHeight: Longint;
        biPlanes: Word;
        biBitCount: Word;
        biCompression: DWORD;
        biSizeImage: DWORD;
        biXPelsPerMeter: Longint;
        biYPelsPerMeter: Longint;
        biClrUsed: DWORD;
        biClrImportant: DWORD;
      end;
     
      TBitmapInfo = record
        bmiHeader: TBitmapInfoHeader;
        bmiColors: array[0..255] of TRGBQuad;
      end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      var BI: TBitmapInfo;
      FillChar(BI, SizeOf(BI), 0);
      BI.bmiHeader.biSize := SizeOf(BI.bmiHeader);
      BI.bmiHeader.biWidth := 455;
      BI.bmiHeader.biHeight := 436;
      BI.bmiHeader.biPlanes := 1;
      BI.bmiHeader.biBitCount := 8;
      BI.bmiHeader.biSizeImage := 456 * 436; // 456 qui est multiple de 4 !
     
      for var I := 0 to 255 do   // palette de gris
      begin
        BI.bmiColors[I].rgbBlue := I;
        BI.bmiColors[I].rgbGreen := I;
        BI.bmiColors[I].rgbRed := I;
        BI.bmiColors[I].rgbReserved := 0;
      end;
     
      var BMF: TBitmapFileHeader;
      BMF.bfType := $4D42;
      BMF.bfOffbits := SizeOf(BMF) + SizeOf(BI);
      BMF.bfSize := BMF.bfOffBits + BI.bmiHeader.biSizeImage;
     
      var F := TMemoryStream.Create;
      F.WriteBuffer(BMF, SizeOf(BMF));
      F.WriteBuffer(BI, SizeOf(BI));
     
      var Dat := TFileStream.Create('..\..\lena455x436-8bit.dat', fmOpenRead);
      var L: TArray<Byte>;
      SetLength(L, 456); // ajouter 1 octet pour avoir des lignes en multiple de 4
      for var Y := 0 to 435 do
      begin
        Dat.Read(L[0], 455);
        F.Write(L[0], 456);  
      end;
      Dat.Free;
     
      F.Position := 0;
     
      Image1.Bitmap.LoadFromStream(F);  // on a maintenant un bête BITMAP
     
      F.Free;
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  6. #6
    Membre du Club

    Profil pro
    senior scientist
    Inscrit en
    Mai 2003
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : senior scientist

    Informations forums :
    Inscription : Mai 2003
    Messages : 79
    Points : 67
    Points
    67
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    une solution assez simple pour gérer un tableau de pixel est de produire un Bitmap dans un Stream
    Astucieux ! ça contourne tous les appels de haut niveau autour de TBitmap.

    Mais ça me paraît assez lent, je trouve en moyenne 2 à 3 ms pour afficher cette toute petite image, supposée déjà en mémoire.
    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
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      var t1, t2: int64;
      tic.StartNew;
     
      var Dat := TFileStream.Create('..\lena455x436-8bit.dat', fmOpenRead);
      var L: TArray<Byte>;
      SetLength(L, 455*436);
      Dat.Read(L, 455*436);
     
      t1 := tic.GetTimeStamp;
     
      for var Y := 0 to 435 do
      begin
        F.Write(L[Y*455], 455);
        F.Position := F.Position + 1;
      end;
      Dat.Free;
     
      F.Position := 0;
     
      Image1.Bitmap.LoadFromStream(F);  // on a maintenant un bête BITMAP
     
      t2 := tic.GetTimeStamp;
      Label1.Text := 'elaps: ' + Format('%8u', [t2 - t1]);    // ==>  25000 ticks en moyenne, soit 2 à 3 ms.
     
    end;

  7. #7
    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 430
    Points
    28 430
    Par défaut
    ça donne quoi si tu charges un Bitmap ? tu peux par exemple enregistrer l'image sur disque pour la recharger.

    car si je ne m'abuse FMX utilise des textures pour le rendu des bitmap, donc tu as transfert de l'image en mémoire vidéo pour créer une texture, et ce n'est pas forcément une opération très rapide.

    quand tu as un bout de code qui semble prendre du temps, il faut toujours vérifier quelle portion est lente, la lecture du .dat, sa conversion, ou finalement le chargement du Stream

    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
     
    procedure TForm1.FormCreate(Sender: TObject);
    var
      t1, t2, t3, t4: Int64;
    begin
      t1 := TThread.GetTickCount64;
      var BI: TBitmapInfo;
      FillChar(BI, SizeOf(BI), 0);
      BI.bmiHeader.biSize := SizeOf(BI.bmiHeader);
      BI.bmiHeader.biWidth := 455;
      BI.bmiHeader.biHeight := 436;
      BI.bmiHeader.biPlanes := 1;
      BI.bmiHeader.biBitCount := 8;
      BI.bmiHeader.biSizeImage := 456 * 436; // 456 qui est multiple de 4 !
     
      for var I := 0 to 255 do   // palette de gris
      begin
        BI.bmiColors[I].rgbBlue := I;
        BI.bmiColors[I].rgbGreen := I;
        BI.bmiColors[I].rgbRed := I;
        BI.bmiColors[I].rgbReserved := 0;
      end;
     
      var BMF: TBitmapFileHeader;
      BMF.bfType := $4D42;
      BMF.bfOffbits := SizeOf(BMF) + SizeOf(BI);
      BMF.bfSize := BMF.bfOffBits + BI.bmiHeader.biSizeImage;
     
      var F := TMemoryStream.Create;
      F.WriteBuffer(BMF, SizeOf(BMF));
      F.WriteBuffer(BI, SizeOf(BI));
     
      t2 := TThread.GetTickCount64;
     
      var Dat := TFileStream.Create('..\..\lena455x436-8bit.dat', fmOpenRead);
      var L: TArray<Byte>;
      SetLength(L, 456);
      for var Y := 0 to 435 do
      begin
        Dat.Read(L[0], 455);
        F.Write(L[0], 456);  // ajouter 1 octet pour avoir des lignes en multiple de 4
      end;
      Dat.Free;
     
     
    //  F.SaveToFile('BITMAP.BMP');
     
      F.Position := 0;
     
      t3 := TThread.GetTickCount64;
      Image1.Bitmap.LoadFromStream(F);  // on a maintenant un bête BITMAP
      t4 := TThread.GetTickCount64;
     
      F.Free;
      ShowMessage(
        (T2 - T1).ToString + 'ms'#13 +
        (T3 - T2).ToString + 'ms'#13 +
        (T4 - T3).ToString + 'ms'#13 +
        (T4 - t1).ToString + 'ms'
      );
    end;
    chez moi ça prend 16ms entre t4 et t1, mais tout se passe entre t4 et t3
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  8. #8
    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 430
    Points
    28 430
    Par défaut
    en regardant le code de LoadFromStream une autre approche est possible

    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
     
      var S := TBitmapSurface.Create;
      S.SetSize(455, 436, TPixelFormat.RGBA);
      var Dat := TFileStream.Create('..\..\lena455x436-8bit.dat', fmOpenRead);
      var Line: TArray<Byte>;
      SetLength(Line, 455);
      for var Y := 435 downto 0 do
      begin
        Dat.Read(Line[0], 455);
        var P: PByte := S.Scanline[y];
        for var x := 0 to 454 do
        begin
          for var c := 0 to 2 do
          begin
            P^ := Line[x];
            Inc(P);
          end;
          P^ := $FF;
          Inc(P);
        end;
      end;
      Image1.Bitmap.Assign(S);
      S.Free;
    NB: j'ai testé d'autres PixelFormat mais ça ne donnait pas le résultat attendu, je n'ai pas creusé, mais en RGBA ça fonctionne en tout cas
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

Discussions similaires

  1. visualisation d'une image
    Par the fog dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 12/06/2012, 10h33
  2. visualisation d'une image en C
    Par Nozraj dans le forum Débuter
    Réponses: 5
    Dernier message: 10/07/2009, 12h08
  3. Afficher une image en visualisation n'importe ou sur la page
    Par Aurelien23 dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 03/03/2006, 20h53
  4. [C#] Visualiser une image
    Par tyraslin dans le forum Windows Forms
    Réponses: 3
    Dernier message: 29/11/2005, 12h03
  5. visualisation et zoom d'une image
    Par julie20 dans le forum Composants VCL
    Réponses: 4
    Dernier message: 11/08/2003, 03h28

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