John Dogget
Messages postés384Date d'inscriptionvendredi 18 juin 2004StatutMembreDernière intervention 7 mai 2009
-
28 janv. 2007 à 22:55
John Dogget
Messages postés384Date d'inscriptionvendredi 18 juin 2004StatutMembreDerniè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.
John Dogget
Messages postés384Date d'inscriptionvendredi 18 juin 2004StatutMembreDerniè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 ...)
John Dogget
Messages postés384Date d'inscriptionvendredi 18 juin 2004StatutMembreDerniè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
cs_Loda
Messages postés814Date d'inscriptionvendredi 3 novembre 2000StatutMembreDernière intervention30 juillet 20093 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.
f0xi
Messages postés4205Date d'inscriptionsamedi 16 octobre 2004StatutModérateurDernière intervention12 mars 202235 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.
John Dogget
Messages postés384Date d'inscriptionvendredi 18 juin 2004StatutMembreDerniè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.
John Dogget
Messages postés384Date d'inscriptionvendredi 18 juin 2004StatutMembreDerniè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.
f0xi
Messages postés4205Date d'inscriptionsamedi 16 octobre 2004StatutModérateurDernière intervention12 mars 202235 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)
f0xi
Messages postés4205Date d'inscriptionsamedi 16 octobre 2004StatutModérateurDernière intervention12 mars 202235 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.
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)