Déclaration de type de fichier dynamique [Résolu]

Messages postés
32
Date d'inscription
mercredi 10 janvier 2007
Dernière intervention
1 septembre 2015
- 9 mai 2012 à 15:07 - Dernière réponse :
Messages postés
32
Date d'inscription
mercredi 10 janvier 2007
Dernière intervention
1 septembre 2015
- 15 mai 2012 à 18:06
Bonjour,

voilà, pour faire simple, j'aurais vraiment besoin de pouvoir transformer un code du genre

Type FichierStructureTexture3C = Record
RVal: array[0..xxx] of Byte; // valeur de la composante rouge
GVal: array[0..xxx] of Byte; // valeur de la composante verte
BVal: array[0..xxx] of Byte; // valeur de la composante bleue
end;
Type FichierST3C = File of FichierStructureTexture3C;

Il s'agit d'un format de fichier pour des textures simples (3 composantes, donc sans plan alpha, j'ai aussi la version avec plan alpha mais là n'est pas le problème) que j'utilise dans un moteur 3D que je cherche à développer depuis environ 2 ans, 0..xxx correspond à la taille d'une ligne de texture, la déclaration de type donne la structure d'un enregistrement dans le fichier où est stockée la texture.

Ce code fonctionne très bien, seulement il est complètement statique et cela suppose que toutes les textures font la même largeur, ce qui n'est pas le cas.
Depuis déjà longtemps, j'ai contourné le problème avec des textures stockées point par point, donc la largeur de la ligne n'a plus d'importance et on se retrouve avec un format de ce style

Type FichierStructureTexture3C = Record
RVal: Byte; // valeur de la composante rouge
GVal: Byte; // valeur de la composante verte
BVal: Byte; // valeur de la composante bleue
end;
Type FichierST3C = File of FichierStructureTexture3C;

Si on connait par ailleurs la largeur de la ligne, cela marche aussi et cela n'empêche pas de charger dans des variables tableau. Cependant le fait de ne pas charger ligne par ligne ralenti considérablement le temps de chargement et , sur un certain nombre de textures assez grandes (512 x 512 en moyenne), c'est très gènant.

Je cherche donc à obtenir un code du type

type
PByteArray = ^TByteArray;
TByteArray = array[0..xxx] of Byte;

//---FICHIER STRUCTURE TEXTURES---// Fichier structure des textures simples (.tx3)
Type FichierStructureTexture3C = Record
RVal: TByteArray; // valeur de la composante rouge
GVal: TByteArray; // valeur de la composante verte
BVal: TByteArray; // valeur de la composante bleue
end;
Type FichierST3C = File of FichierStructureTexture3C;
//---###---//

où je pourrait définir dynamiquement la taille de chaque texture lors du chargement. Je sais que cela doit être possible car "Les types ne peuvent pas être des chaînes longues, des tableaux dynamiques, des types Variant, des interfaces ou des types structurés contenant ces mêmes types.
Par contre, ce peut être des pointeurs sur ces types." (extrait de la documentation de Delphi 6)

Seulement, voilà des mois que j'essaie de faire fonctionner cette solution, sans succès. J'ai essayé beaucoup de choses, parfois idiotes même, en pensant que ... mais non !
Voilà, si quelqu'un peut m'apporter une réponse ou un morceau de réponse, ... cela me permettrait d'avancer d'un grand pas dans mon projet.

md21
Afficher la suite 

Votre réponse

8 réponses

Meilleure réponse
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
- 10 mai 2012 à 13:49
3
Merci
Salut,

je me disais bien que le sujet m'étais familier:
pour mémoire

ton problème vient du choix de fichier ... le fichier séquentiel implique de connaitre la taille des données avant la compilation ... il faut donc utiliser une autre méthode et je suis du même avis que Caribensila ... c'est le moyen le plus simple pour stocker des Bitmaps.

Maintenant, si j'ai bien compris, tu souhaites les stocker dans ton format.
Dans ce cas il faut "ruser" ... comme la taille des données n'est pas fixe il faut les renseigner avant d'y écrire les informations.
Ex.
On a un entête, de taille fixe, avec les infos importantes pour nous.
type
  TEntete = packed record
    Nom: string[8]; // pas indispensable
    BitPerPixel: Byte;
    Width: Integer;
    Height: Integer;
  end; 


à partir de là on peut calculer la taille des lignes et la taille totale des données qui sont ajoutées à la suite de l'entête

ce qui donne un fichier :
#entête1#données1#entête2#données2 ... etc
partant de là on peut lire/écrire les données (pixels) en une fois ou ligne par ligne ou encore pixel par pixel ...

Mais évite l'utilisation du type "file of" ça ne fonctionnera pas ici. Utilise les Streams à la place et il sont plus performants
[hr]@+Cirec
[hr]

Merci Cirec 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 90 internautes ce mois-ci

Commenter la réponse de Cirec
Meilleure réponse
Messages postés
2684
Date d'inscription
jeudi 15 janvier 2004
Dernière intervention
26 juillet 2018
- 10 mai 2012 à 14:10
3
Merci

Merci Caribensila 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 90 internautes ce mois-ci

Commenter la réponse de Caribensila
Meilleure réponse
Messages postés
2684
Date d'inscription
jeudi 15 janvier 2004
Dernière intervention
26 juillet 2018
- 10 mai 2012 à 19:46
3
Merci
... Tu ne pourras pas stocker directement un "array of byte" dans un fichier binaire car les tableaux dynamiques sont des pointeurs.
En revanche tu pourras stocker les valeurs des cellules de ton tableau dans un fichier binaire, et, à la relecture, recréer un "array of byte" de taille appropriée et y copier les données puisées dans le fichier...

Mais je te laisse découvrir ce magnifique outil qu'est le fichier binaire...

Merci Caribensila 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 90 internautes ce mois-ci

Commenter la réponse de Caribensila
Messages postés
2684
Date d'inscription
jeudi 15 janvier 2004
Dernière intervention
26 juillet 2018
- 9 mai 2012 à 16:35
0
Merci
Salut,

Pourquoi ne pas stocker tes textures sous forme de Bitmap dans un fichier binaire, tout simplement ?
Commenter la réponse de Caribensila
Messages postés
32
Date d'inscription
mercredi 10 janvier 2007
Dernière intervention
1 septembre 2015
- 9 mai 2012 à 17:09
0
Merci
salut, merci de ta réponse

Je vais te donner un peu plus de détails:

Mon moteur 3D utilise des matrices de nombres comme textures comme tu as vu. Pourquoi ? parce que je n'ai plus à m'occuper de pixels, il reste uniquement des calculs et l'image finale n'est restituée qu'à la fin du traitement.
J'ai mesuré à l'époque, traiter des nombres était en moyenne 700 fois plus rapide que traiter des pixels, ce qui permet d'envisager un moteur de jeu 3D (encore que malgré cela je suis toujours beaucoup trop lent sur les grosses résolutions mais j'y travaille).

A la base les textures sont des images de type bitmap ou jpg. Je les transforme en fichiers textures (.tx3 ou .tx4 selon qu'il y a ou non un plan alpha) pour obtenir un fichier avec que des nombres. Alors oui, je pourrai charger directement des images et les convertir en nombres dans les variables tableau utilisées par le moteur, seulement c'est également très long (même avec scanline), la machine devant "lire" les pixels.

Quand je crée une texture, peu importe le temps que ça met, dans l'éditeur on a tout le temps et puis on ne crée la texture qu'une seule fois. C'est au chargement qu'il faut être rapide. Une texture de 512 x 512 prend entre 1 et 2 s en la chargeant point par point et environ 10 x moins de temps soit 2/10 s en la chargeant ligne par ligne (donc 512 points à la fois). Pour concevoir un niveau, il faut des dizaines, voire des centaines de textures, c'est pourquoi j'aurai vraiment besoin de gagner sur les temps de chargement;

Alors ton idée est peu-être très bonne, au vu de ces quelques explications, si tu penses que ça peut marcher je suis intéressé; Je t'avoue que je ne sais pas comment on stocke un bitmap dans un fichier binaire ... mais c'est à voir

md21
Commenter la réponse de md21
Messages postés
32
Date d'inscription
mercredi 10 janvier 2007
Dernière intervention
1 septembre 2015
- 10 mai 2012 à 18:31
0
Merci
@Cirec

effectivement que le sujet est familier. J'ai commencé ce projet il y a bientôt 2 ans à qq jours près, il est bien avancé, j'obtiens des résultats plutôt prometteurs mais il reste encore pas mal à faire. Comme tu vois je ne me décourage pas facilement
Merci de ta réponse, j'avoue que je n'ai pas tout compris vraiment à fond, mais apparement les streams sont très puissants et je ferai bien de m'y mettre. C'est vrai que j'utilise parfois des codes un peu "old school" (comme mon moteur d'ailleurs)

@Cari

merci, j'ai téléchargé et essayé ton code. J'ignorai que l'on pouvais créer ce genre de fichier qui convient pour tout, c'est génial.

Si il est possible de stocker des "array of byte" définis dynamiquement auparavant pour du ligne par ligne, ou encore mieux des "array of array of byte" toujours dynamiques pour toute une image c'est exactement ce dont j'aurais besoin.
Dans le fichier j'ai besoin d'un tableau par composante de couleur (R, G, B) que je rempli en analysant l'image avec scanline (d'après un code que vous m'aviez montré tous les deux au début). Certaine textures ont un plan alpha qui est de même nature que les tableaux des couches RGB et renseigne la transparence associée au pixel entre 0 et 255. Pour ce faire j'analyse lors de la création de la texture une deuxième image en dégradé de gris, issue à la base de la première mais travaillée avec photoshop ou autre et traduisant les zones à voir plus ou moins.


md21
Commenter la réponse de md21
Messages postés
32
Date d'inscription
mercredi 10 janvier 2007
Dernière intervention
1 septembre 2015
- 10 mai 2012 à 20:21
0
Merci
Merci beaucoup, je vais voir ça. Si j'ai bien compris on peut stocker le tableau de manière globale (enfin les cellules) dans le fichier binaire et bien sûr recréer un tableau dynamique au chargement

md21
Commenter la réponse de md21
Messages postés
32
Date d'inscription
mercredi 10 janvier 2007
Dernière intervention
1 septembre 2015
- 15 mai 2012 à 18:06
0
Merci
Salut Caribensila,

grâce à tes conseils, je viens de créer mon premier fichier binaire sur la base d'un array of array of byte avec des nombres aléatoires, je stocke la largeur et la hauteur en integer et ensuite les valeurs en byte. A la lecture, je dimensionne un autre array of array of byte et je replace les valeurs dedans. C'est entièrement dimensionnable !

Il me reste à essayer avec des vraies textures pour voir si je gagne ou non du temps par rapport à mon système actuel, mais je pense que oui.

Je vais pouvoir également me servir des fichiers binaires pour les fichiers de mosaïquage (qui contiennent les données des sols et des plafonds) qui me posaient encore plus de problèmes. Jusqu'alors j'utilisait uniquement des imports en format txt, mais c'est une solution provisoire.

voici mon code:
unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, StdCtrls;

type
  TMainFiche = class(TForm)
    GRID_IN: TStringGrid;
    B_Enregistrer: TButton;
    B_Charger: TButton;
    GRID_OUT: TStringGrid;
    procedure CREER(Sender: TObject);
    procedure CDE_Enregistrer(Sender: TObject);
    procedure CDE_Charger(Sender: TObject);
  private
    { Déclarations privées }
    procedure Afficher_GRID_OUT;
  public
    { Déclarations publiques }
  end;

var
  MainFiche: TMainFiche;
  Largeur, Hauteur: Integer;
  V_Tableau_IN:  array of array of Byte;
  V_Tableau_OUT: array of array of Byte;

implementation

uses StrUtils, Math, DateUtils;

{$R *.dfm}
{$R manifest.res}

procedure TMainFiche.CREER(Sender: TObject);
var
  X, Y: Integer;
begin
Largeur := 5;
Hauteur := 4;

Setlength(V_Tableau_IN,Largeur,Hauteur); // colonnes, lignes

//---Start-Mise en place de données aléatoires dans V_TABLEAU_IN et affichage dans GRID_IN---//
Randomize;
For X := 0 to Largeur - 1 do
  For Y := 0 to Hauteur - 1 do
    Begin
      V_Tableau_IN[X,Y] := Random(256);
      GRID_IN.Cells[X,Y] := IntToStr(V_Tableau_IN[X,Y]);
    end;
//---End---Mise en place de données aléatoires dans V_TABLEAU_IN et affichage dans GRID_IN---//
end;

procedure TMainFiche.CDE_Enregistrer(Sender: TObject);
var
  X, Y: Integer;
  FileStrm: TFileStream;
begin
if FileExists('Texture.tx3') then DeleteFile('Texture.tx3');

FileStrm := TFileStream.Create('Texture.tx3',fmCreate or fmShareExclusive); // ouverture d'un flux en création de fichier et de façon exclusive à l'application

Try
  FileStrm.Position := 0; // on se positionne au début du flux

  FileStrm.WriteBuffer(Largeur,SizeOf(Integer));            // Nb de colonnes
  FileStrm.WriteBuffer(Hauteur,SizeOf(Integer));            // Nb de lignes
  For Y := 0 to Hauteur - 1 do
    For X := 0 to Largeur - 1 do
      FileStrm.WriteBuffer(V_Tableau_IN[X,Y],SizeOf(Byte)); // données

  FileStrm.Free;
Except
end;
end;

procedure TMainFiche.CDE_Charger(Sender: TObject);
var
  X, Y, L, H, Taille: Integer;
  FileStrm: TFileStream;
begin
if FileExists('Texture.tx3') then
  Begin
    FileStrm := TFileStream.Create('Texture.tx3',fmOpenRead or fmShareExclusive); // ouverture d'un flux en lecture de fichier et de façon exclusive à l'application

    Try
      FileStrm.Position := 0; // on se positionne au début du flux

      FileStrm.ReadBuffer(L,SizeOf(Integer));                   // Nb de lignes
      FileStrm.ReadBuffer(H,SizeOf(Integer));                   // Nb de colonnes
      Setlength(V_Tableau_OUT,L,H);                             // colonnes, lignes
      For Y := 0 to H - 1 do
        For X := 0 to L - 1 do
          FileStrm.ReadBuffer(V_Tableau_OUT[X,Y],SizeOf(Byte)); // données

      FileStrm.Free;
    Except
    end;
    Afficher_GRID_OUT;
  end;
end;

procedure TMainFiche.Afficher_GRID_OUT;
var
  X, Y: Integer;
begin
For X := 0 to Length(V_Tableau_OUT) - 1 do
  For Y := 0 to Length(V_Tableau_OUT[X]) - 1 do
    GRID_OUT.Cells[X,Y] := IntToStr(V_Tableau_OUT[X,Y]);
end;

end.


md21
Commenter la réponse de md21

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.