Instructions qui bloquent le programme

Résolu
John Dogget Messages postés 384 Date d'inscription vendredi 18 juin 2004 Statut Membre Dernière intervention 7 mai 2009 - 28 janv. 2007 à 22:55
John Dogget Messages postés 384 Date d'inscription vendredi 18 juin 2004 Statut Membre Dernière intervention 7 mai 2009 - 30 janv. 2007 à 18:04
Salut à tous.

J'ecris un programme dont le but est de générer une image.
Mon soucis, c'est qu'au moment de générer celle-ci, le traitement prends toutes les ressources et le programme semble bloqué. Une fenetre est censé afficher la progression de l'opération, elle ne n'affiche pas non plus (même cause je pense).
J'utilise une simple boucle avec un "Application.ProcessMessages" à l'interieur mais ça n'as pas l'air très efficace.

Vous auriez une idée pour éviter ça ?

13 réponses

John Dogget Messages postés 384 Date d'inscription vendredi 18 juin 2004 Statut Membre Dernière intervention 7 mai 2009
30 janv. 2007 à 18:04
Oups, j'vais pas vu la deuxième page
Pas grâve, le toute première version de ton code me convient bien (et pis header, chunk bidule truc je sais même pas ce que c'est alors ...)
3
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
28 janv. 2007 à 22:58
Salut,

c'est bien beau tout ça mais sans code on ne peut rien pour toi

 
@+
Cirec

<hr size="2" />
0
John Dogget Messages postés 384 Date d'inscription vendredi 18 juin 2004 Statut Membre Dernière intervention 7 mai 2009
28 janv. 2007 à 23:24
Ok

Bon alors, j'ai trois fiches :
- une qui affiche l'image (Form1)
- une qui permet de choisir les parametres de l'image à calculer (Form2)
- une qui indique la progression de calcul de l'image (qui devrais indiquer ) (Form3)

Quand les parametres sont saisis, j'affiche la troisième fiche pour indique la progression, et j'affiche en même temps l'image sur la première fiche.

Voilà le bout de code qui affiche l'image et la progression (dans form3) :

while IndexPixel<nbPixelsImage do
  begin
    Application.ProcessMessages;
    Read(FichierAConvertir,UnPixel);
    Form1.Image1.Canvas.Pen.Color:=ConvertirPixel(UnPixel);
    Form1.Image1.Canvas.Rectangle(PosX,PosY,PosX+2,PosY+2);
    Inc(PosX);
    if PosX>DimensionsImage.Largeur then
    begin
      PosX:=0;
      Inc(PosY);
    end;
    Inc(IndexPixel);
    Gauge1.Progress:=IndexPixel;
  end;

J'ai placé ce code dans l'evennement "OnShow" de la form3.
L'image s'affiche correctement dans form1, mais form3 ne s'affiche pas
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
28 janv. 2007 à 23:59
de quel type est le FichierAConvertir

je suppose que le Read te sert à lire les infos dans le fichier ...

si c'est le cas tu devrais déjà avoir une structure du genre :

      while not Eof(FichierAConvertir) do
      begin
        Read(FichierAConvertir, UnPixel);
      end;
      CloseFile(FichierAConvertir);

ensuite que fait la procedure : ConvertirPixel
 
@+
Cirec

<hr size="2" />
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
29 janv. 2007 à 09:20
Salut,

c'est simple, lors que le "OnShow" de la form3." est FINIT, ta form s'affiche. Donc tu ne peux pas voir les changement d'affichage que tu fait DANS le OnShow !

perso, si le traitment est long je te conseille de
- faire le traitement dans un thread
- ajouter une methode form3.StepProgressBar. (sans parametre, comme ça tu peux la syncroniser avec le thread)
- d'appeler ton .Step tout les 5% de calcul environ (si tu l'appel tout les pixel de ton image, tu vas passer autant de temps a faire avancer ta bar qu'a convertire ton image)

A+

Loda
<hr size="2" width="100%" />Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
0
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
29 janv. 2007 à 11:10
while IndexPixel<nbPixelsImage do
  begin
    Application.ProcessMessages;
    Read(FichierAConvertir,UnPixel);
    Form1.Image1.Canvas.Pen.Color:=ConvertirPixel(UnPixel);
    Form1.Image1.Canvas.Rectangle(PosX,PosY,PosX+2,PosY+2);
    Inc(PosX);
    if PosX>DimensionsImage.Largeur then
    begin
      PosX:=0;
      Inc(PosY);
    end;
    Inc(IndexPixel);
    Gauge1.Progress:=IndexPixel;
  end;


???????????!!!! BEUARRRRK!

qu'est-ce que c'est que ce machin la!

alors,
- sois plus clair dans tes explications : que fait ce process ?
- qui est FichierAConvertir et dans quel format se trouve t'il ?
- que fait la fonction ConvertirPixel ?
- quel est le resultat attendus ?

si tu me dis tout cela, je te filerais une methode 500 fois plus rapide que ton machin bidule.

<hr size="2" width="100%" />Croc (click me)
0
John Dogget Messages postés 384 Date d'inscription vendredi 18 juin 2004 Statut Membre Dernière intervention 7 mai 2009
29 janv. 2007 à 17:49
> fOxi
Je suis bien content que tu sois un boss de Delphi ...
Je ne suis pas professionnel de la programmation, j'ai pas non plus la science infuse, dans le cas contraire je viendrais pas poster ici,  surtout pour récolter des "beuaarrrk"

Jvais me demerder, merci à toi d'avoir donner de ton temps ...

> loda
Je vais essayer de "threadiser" tout ça
Pourquoi pas enlever aussi carrement la fenetre de progression qui n'est finalement pas très utile.
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
29 janv. 2007 à 21:20
Pourquoi ne donnes tu pas tout simplement les informations que l'on te demande  
@+
Cirec

<hr size="2" />
0
John Dogget Messages postés 384 Date d'inscription vendredi 18 juin 2004 Statut Membre Dernière intervention 7 mai 2009
29 janv. 2007 à 22:12
Reprenons depuis le début alors

Ce que je voudrais faire, c'est afficher n'importe quel fichier sous la forme d'une image.
Pour ça, j'utilise un type que je défini comme ça

Type TUnPixel=record
  ComposanteB:byte;
  ComposanteG:byte;
  ComposanteR:byte;
end;

Mon fichier sera donc ouvert comme un fichier d'enregistrement TUnPixel.
Ensuite, je lie chaque enregistrement du fichier et j'affiche un point de la couleur correspondant à celui-ci, la procedure "ConvertirPixel" servant alors à determiner la couleur correspondant à chaque pixel.

Je ne peux pas utiliser directement un "oef" vu que le fichier ne contient pas forcement un nombre fini d'enregistrements (je risque de perdre le dernier enregistrement lors de la lecture).

Pour l'instant, j'obtiens bien une image, mais comme je l'ai dis, le processus bloque le programme.
0
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
30 janv. 2007 à 04:23
alors, john, depuis le temps tu devrais savoir qu'il faut me lire au
dela du 3eme degré ... et que si je vanne comme ça c'est que j'ai un
truc pour toi sous le coude ...
non mais ...
faut arreter
d'etre aussi agressif quand on se fait vanner ... qui aime bien chatie
bien ... si je te vanne pas, c'est que j't'aime pas,
alors molo sur les nerfs.

sinon avec tes precisions je peu te donner cela :
methode hyper rapide (~32ms pour un fichier de 4Mo)
methode trés amusante a tester sur des bitmaps 24bits d'origine (laisser le downto dans la boucle dans ce cas) :

procedure NimpToBitmap(const FileName :string; BmpDest :TBitmap; const DesiredWidth :integer);
type
  T24Bit    = array[0..2] of byte;   // nos 3 couleurs : Rouge (0) vert (1) bleu (2)
  pScanLine = ^TScanLine;            // pour Bitmap.Scanline
  TScanLine = array[word] of T24Bit; // une ligne de pixels 24 bits

var TFS   : TFileStream;             // le stream pour le fichier, n'importe quel fichier
    SCL   : pScanLine;               // la variable pour Bitmap.Scanline;
    SSZ,Y : integer;                 // Taille de la ligne, Compteur pour la boucle
begin
  // si le fichier n'existe pas on sort!
  if not FileExists(FileName) then
     exit;

  // sinon on ouvre le stream
  TFS := TFileStream.Create(FileName, fmOpenRead);
  try
    // on fixe le format des pixels en 24 bits
    BmpDest.PixelFormat := pf24bit;
    // on calcul la taille de la ligne *3 24bits, shr 2 32bits, shr 1 = 16bits
    SSZ                 := DesiredWidth * 3;

    // on fixe les dimensions du bitmap en sortie
    BmpDest.Width       := DesiredWidth;
    BmpDest.Height      := round( TFS.Size / SSZ );

    // precision : on peu inverser le sens de la boucle (to / downto)
    // pour influencer l'apparence du bitmap en sortie (mirror)
    for Y := BmpDest.Height-1 downto 0 do begin

        // on recupere le pointeur sur la ligne de pixel Y de BmpDest
        SCL := BmpDest.ScanLine[Y];

        // sans chercher midi a quatorze heure, on remplis SCL directement avec ReadBuffer
        TFS.ReadBuffer(SCL^, SSZ);

        // on zap la fin si il reste pas assé d'octet dans le flux pour faire une ligne.
        if SSZ > (TFS.Size - TFS.Position) then
           break;
        // pwned!
    end;
  finally
    // enfin on libere TFS
    TFS.Free;
  end;
end;

// piti exemple d'utilisation :
procedure TForm1.ouvrir1Click(Sender: TObject);
begin
  if OpenDialog1.Execute then
     // on balance directement dans un bitmap vide d'un TImage...
     NimpToBitmap(OpenDialog1.FileName, image1.Picture.Bitmap, 1280);
end;

on peu egalement placer un buffer temporaire pour ensuite redimensioner l'image avec un stretchdraw qui est beaucoup plus rapide que de faire des rectangles de tailles quelquonque sur un canvas (ça c'est la methode a roger).

alors, merci qui ? papy brossar ou copaing f0xi ? (fleur ... poum)

<hr size="2" width="100%" />Croc (click me)
0
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
30 janv. 2007 à 04:36
ah, precision on peu remplacer :

        if SSZ > (TFS.Size - TFS.Position) then
           break;

par

        if SSZ > (TFS.Size - TFS.Position) then
           SSZ := TFS.Size - TFS.Position;

si on veux recuperer absolument tout les octets.

autre precision, un bitmap vide, dans un timage, est peint en blanc quand on affecte Width et Height.
on peu changer cela tout simplement avec un Fillrect dans le canvas du bitmap.

Bitmap.Canvas.Brush := couleur;
Bitmap.Canvas.Fillrect(Rect(0, 0, Bitmap.Width, Bitmap.Height));

car le dernier pixel, si le nombre d'octet dans le flux est insuffisant, prendras la couleur existante + le ou les derniers octets du flux.
exemple :

le fond est blanc : $FFFFFF
le dernier octet vaut $80
la couleur du pixel final serat $FFFF80 (un cyan donc)

ce qui veut dire qu'on devrait toujours initialiser notre bitmap en noir, pour avoir des valeur nulle pour le dernier pixel quand le flux est trop court.
<hr size="2" width="100%" />Croc (click me)
0
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
30 janv. 2007 à 04:46
ah encore une autre precision car je pense que tu risque de te poser la question :

puisqu'on sait que :

Tz = W*H*Pz

(
Tz = Taille en octet
W = largeur
H  = hauteur
Pz = tailles des pixels (en octets)
)

donc

W = Tz / (H*Pz)
H = Tz / (W*Pz)
Pz = Tz / (W*H)

simple non ? c'est juste au cas ou tu te demande comment on determine un des elements par rapport a d'autres.

par contre la je parle d'un ensemble de pixels en mode raw (données brute) sans signature, header, chunks ...

<hr size="2" width="100%" />Croc (click me)
0
John Dogget Messages postés 384 Date d'inscription vendredi 18 juin 2004 Statut Membre Dernière intervention 7 mai 2009
30 janv. 2007 à 18:01
HS
Je vais pas m'excuser pour tes vannes, et faut bien que tu comprennes que ton humour particulier ne peut pas passer chez tout le monde ...
/HS

Pour le code, effectivement c'est bien plus rapide/intelligent que le mien, je m'en vais tester tout ça dés que possible.
Merci quand même
0
Rejoignez-nous