Instructions qui bloquent le programme [Résolu]

John Dogget 390 Messages postés vendredi 18 juin 2004Date d'inscription 7 mai 2009 Dernière intervention - 28 janv. 2007 à 22:55 - Dernière réponse : John Dogget 390 Messages postés vendredi 18 juin 2004Date d'inscription 7 mai 2009 Dernière intervention
- 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 ?
Afficher la suite 

Votre réponse

13 réponses

Meilleure réponse
John Dogget 390 Messages postés vendredi 18 juin 2004Date d'inscription 7 mai 2009 Dernière intervention - 30 janv. 2007 à 18:04
3
Merci
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 ...)

Merci John Dogget 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 93 internautes ce mois-ci

Commenter la réponse de John Dogget
Cirec 4231 Messages postés vendredi 23 juillet 2004Date d'inscription 3 août 2018 Dernière intervention - 28 janv. 2007 à 22:58
0
Merci
Salut,

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

 
@+
Cirec

<hr size="2" />
Commenter la réponse de Cirec
John Dogget 390 Messages postés vendredi 18 juin 2004Date d'inscription 7 mai 2009 Dernière intervention - 28 janv. 2007 à 23:24
0
Merci
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
Commenter la réponse de John Dogget
Cirec 4231 Messages postés vendredi 23 juillet 2004Date d'inscription 3 août 2018 Dernière intervention - 28 janv. 2007 à 23:59
0
Merci
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" />
Commenter la réponse de Cirec
cs_Loda 900 Messages postés vendredi 3 novembre 2000Date d'inscription 30 juillet 2009 Dernière intervention - 29 janv. 2007 à 09:20
0
Merci
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.
Commenter la réponse de cs_Loda
f0xi 4304 Messages postés samedi 16 octobre 2004Date d'inscription 9 mars 2018 Dernière intervention - 29 janv. 2007 à 11:10
0
Merci
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)
Commenter la réponse de f0xi
John Dogget 390 Messages postés vendredi 18 juin 2004Date d'inscription 7 mai 2009 Dernière intervention - 29 janv. 2007 à 17:49
0
Merci
> 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.
Commenter la réponse de John Dogget
Cirec 4231 Messages postés vendredi 23 juillet 2004Date d'inscription 3 août 2018 Dernière intervention - 29 janv. 2007 à 21:20
0
Merci
Pourquoi ne donnes tu pas tout simplement les informations que l'on te demande  
@+
Cirec

<hr size="2" />
Commenter la réponse de Cirec
John Dogget 390 Messages postés vendredi 18 juin 2004Date d'inscription 7 mai 2009 Dernière intervention - 29 janv. 2007 à 22:12
0
Merci
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.
Commenter la réponse de John Dogget
f0xi 4304 Messages postés samedi 16 octobre 2004Date d'inscription 9 mars 2018 Dernière intervention - 30 janv. 2007 à 04:23
0
Merci
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)
Commenter la réponse de f0xi
f0xi 4304 Messages postés samedi 16 octobre 2004Date d'inscription 9 mars 2018 Dernière intervention - 30 janv. 2007 à 04:36
0
Merci
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)
Commenter la réponse de f0xi
f0xi 4304 Messages postés samedi 16 octobre 2004Date d'inscription 9 mars 2018 Dernière intervention - 30 janv. 2007 à 04:46
0
Merci
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)
Commenter la réponse de f0xi
John Dogget 390 Messages postés vendredi 18 juin 2004Date d'inscription 7 mai 2009 Dernière intervention - 30 janv. 2007 à 18:01
0
Merci
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
Commenter la réponse de John Dogget

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.