begin process at 2010 02 10 01:53:23
  Trouver un code source :
 
dans
 
Accueil > Forum > 

Archive C#

 > 

Archives

 > 

Graphique

 > 

GDI+, grosses images, mosaique...


Derniers messages déposésPoser une question dans le forum ou lancer une discussion

GDI+, grosses images, mosaique...

mercredi 9 février 2005 à 10:30:27 | GDI+, grosses images, mosaique...

MorpionMx

Membre Club Administrateur CodeS-SourceS

Bonjour a tous,

Voila, j'affiche dans un panel une image, que je peux resizer. Quand la longueur ou la hauteur de l'image est plus petite que celle du panel, je la raffiche au dessus et en dessous (affichage en mosaïque, quoi)
Mais le problème, c'est que parfois, ce sont des bitmap qui peuvent peser tres lourds (500 ko a 1 Mo...)
Autant vous dire que :
Plus l'image est affichée de fois, plus la taille en mémoire augmente
Plus l'image est lourde, plus l'affichage de la mosaïque est lent. (GDI+ en managé, c'est folklo  )

Voici deja un bout de code :

private Image picture;
private Point pictureLocation; // Endroit ou on dessinera l'image
private Size pictureSize; // Taille de l'image
private Rectangle pictureDisplayRect; // Associe Picturelocation et Picturesize
private byte mosaicRight = 0;
private byte mosaicDown = 0;

...

public void Zoom(int zoom)
{
pictureSize.Width += (int)(0.02f * (pictureSize.Width / 100) * zoom);
pictureSize.Height += (int)(0.02f * (pictureSize.Height / 100) * zoom);
ModifyRects();
}

private void ModifyRects()
{
pictureDisplayRect = new Rectangle(pictureLocation, pictureSize);
this.Invalidate();
}

private void Mosaique(Graphics g)
{
if(mosaicRight < 255 && pictureDisplayRect.X + (mosaicRight * pictureDisplayRect.Size.Width) < this.Size.Width)
++mosaicRight;
if(mosaicRight > 0 && (mosaicRight) * pictureDisplayRect.Size.Width > this.Size.Width)
--mosaicRight;
if(mosaicDown < 255 && (mosaicDown) * pictureDisplayRect.Size.Height < this.Size.Height)
++mosaicDown;
if(mosaicDown > 0 && (mosaicDown) * pictureDisplayRect.Size.Height > this.Size.Height)
--mosaicDown;

for(int i = 0; i <= mosaicRight; i++)
{
   for(int j = 0; j <= mosaicDown; j++)
   {
      g.DrawImage(picture, pictureDisplayRect.X + (i * pictureDisplayRect.Width),
                                    pictureDisplayRect.Y + (j * pictureDisplayRect.Height),
                                    pictureDisplayRect.Width,
                                     pictureDisplayRect.Height); 
   }
}
}

La méthode Mosaïque est appelée par la fonction onPaint, et la méthode Zoom par le mouvement de la molette (c'est ainsi qu'on resize l'image)
Donc l'appel des méthodes se fait ainsi
Zoom -> ModifyRects -> OnPaint -> Mosaique

Comme je l'ai dit, c'est vraiment loin d'etre rapide tout ca... surtout qu'apres je drois rafficher une autre image par dessus, et du dessin...
Alors j'ai cherché plusieurs pistes.
Premierement, le code unsafe. Ca me paraissait la meilleure façon d'optimiser la chose. Cependant, je fait aucun reel "traitement" sur l'image, je l'affiche ou j'en affiche plusieurs. Donc je suis toujours dépendant de la méthode DrawImage... Les pointeurs ne peuvent pas me servir. (si ?)
Je me suis donc dit que j'allais charger l'image dans un MemoryStream, et que j'éeffectuerais a la volée le resize d'image dedans, ainsi, plus l'image serait petite, moins elle peserait, et moins ce serait lent...Que neni, a force de recreer l'image a chaque mouvement de molette, ca améliore rien du tout... loin de la !

Alors je fais appel a vous :
Auriez vous une bonne technique pour améliorer tout ca ? Comment procéderiez vous ?
Pour ce qui est de l'algorithme en mosaique, vous avez pas un exemple meilleur ? (sachant que la, ce n'est que le début, ca sert juste a remplir sur la droite et le bas, mais il faudrait aussi que je remplisse en haut et a gauche, et quand je "bouge l'image", pas seulement que je la retrecit)

Merci par avance de votre aide
Mx

mercredi 9 février 2005 à 18:47:13 | Re : GDI+, grosses images, mosaique...

coq

Administrateur CodeS-SourceS
Déjà tu devrais utiliser un buffer : par exemple tu dessines ta mosaique sur une instance de Bitmap que tu dessines en un coup après avec DrawImageUnscaled



Cocoricoooooooo !!!!
coq
MVP Visual C#
mercredi 9 février 2005 à 18:57:04 | Re : GDI+, grosses images, mosaique...

MorpionMx

Membre Club Administrateur CodeS-SourceS
J'utilises deja un buffer (qui est le graphics g passé en parametre).
Pour le DrawImageUnscaled, je le fais lors du dessin du buffer, dans la méthode Paint(). Par contre, si j'utilises le DrawImageUnscaled() dans la creation de la mosaique, ca bug. (mais j'ai pas essayé de corriger, faudrait que je vois ca)

Je me suis tourné vers l'api win32 et BitBlt. Ca améliore beaucoup les perfs en ce qui concerne l'affichage en mosaïque. Par contre, quand il n'y a l'image dessinée qu'une seule fois, on dirait que c'est plus lent que le DrawImage().
Jvais encore continuer a chercher, Mes nouvelles decouvertes sont toutes chaudes la, y'a surement moyen d'améliorer ca encore un peu.

Merci pour ton intervention coq

Mx
mercredi 9 février 2005 à 19:04:44 | Re : GDI+, grosses images, mosaique...

coq

Administrateur CodeS-SourceS
Ok
Juste par curiosité tu veux faire quoi au juste ?



Cocoricoooooooo !!!!
coq
MVP Visual C#
mercredi 9 février 2005 à 19:42:22 | Re : GDI+, grosses images, mosaique...

MorpionMx

Membre Club Administrateur CodeS-SourceS
Il faut que je remplisse une forme quelconque par une image, ou  plusieurs fois cette image selon sa taille.
Donc je peux déplacer l'image et la redimensionner, la contrainte principale etant qu'il n'y ait pas de "zone blanche" dans cette forme grace au dessin en mosaïque (ce qui n'est pas encore le cas, avec ma fonction)

Pour info, voici ma méthode Paint

        protected override void OnPaint(PaintEventArgs e)
        {
            if(backBuffer == null)
                backBuffer = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);

            Graphics g = Graphics.FromImage(backBuffer);
            g.Clear(this.BackColor);

            if(highQuality)
            {
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.PixelOffsetMode = PixelOffsetMode.HighQuality;
            }

            if(picture != null)
                Mosaique(g);
                //g.DrawImage(picture, pictureDisplayRect, pictureRect, GraphicsUnit.Pixel);

             ...(Autres dessins dans g)

            g.Dispose();
            e.Graphics.DrawImageUnscaled(backBuffer, 0, 0);
        }

La variable HighQuality etant un booleen qui est false lors du mouseDown (Un mouseMove permet de bouger l'image, donc autant ne pas dessiner l'image en haute qualité pendant le déplacement de celle ci).

Les images sont du type 945 x 1890 x 24 en Jpg (600 ko pour cet exemple)(j'avais dit bitmap dans mon premier post)
Si tu as d'autres astuces pour améliorer les perfs, Je suis preneur ;)

Mx
mercredi 9 février 2005 à 20:05:15 | Re : GDI+, grosses images, mosaique...

APWEB

Membre Club
Apparement tu peut utiliser les pointeurs , avec la methode LockBits et UnLockBits pour travailler en memoire dessus.

AP
mercredi 9 février 2005 à 20:11:43 | Re : GDI+, grosses images, mosaique...

MorpionMx

Membre Club Administrateur CodeS-SourceS
Oui oui,  mais, pour quel "travail en mémoire" je pourrais utiliser ces lockbits, sachant que la seule chose que je fais c'est afficher des images ?
J'étais parti pour cette solution, mais j'ai pas trouvé dans quel cas je pourrais m'en servir ... ?


Mx
jeudi 10 février 2005 à 21:29:37 | Re : GDI+, grosses images, mosaique...

TUHABITES

Salut,
s'il ne s'agit que de l'affichage pourquoi n'utilises-tu pas directx?

          Tuhabites.
         
vendredi 11 février 2005 à 09:26:42 | Re : GDI+, grosses images, mosaique...

MorpionMx

Membre Club Administrateur CodeS-SourceS
Si tu veux, si ca avait été pour moi, je l'aurais certainement fait en DirectX.
Mais bon, la tu vois, c'est une appli "de bureau", destiné pour un parc de PC tres hétérogène, parfois avec des cartes graphiques peut-etre vieilles ou désuettes.
Donc je préfère que ce type de manipulation  soit traitée "softwarement".

Bitblt répond plutot a mes attentes, donc je pense que je vais l'adopter.
Je ferais une source, je pense la semaine prochaine, avec un exemple de son utilisation.

Petite question, sachant que j'utilises les fonctions la dll "gdi32.dll", est-ce que ce sera toujours géré par longhorn ?

Mx


Cette discussion est classée dans : image, width, height, size, picturedisplayrect


Répondre à ce message

Sujets en rapport avec ce message

creation d'un objet par le code [ par fafelle1 ] Salut tout le monde, Voila j'ai un souci pour créer un pictureBox par le code...J'ai bien l'impression qu'il est créé mais il ne s'affiche pas a l'ecr Dessiner un rond plein [ par fcolo ] Bonjour,Je souhaiterai créer un live une icone représantant un rond plein.J'arrive à créer un rond, mais je ne sasi pas comment remplir l'intérieur.Je Méthode générique pour centrer des controles [ par babe59 ] Bonjour j'essaye d'écrire une méthode pour centrer (horizontal) les contrôles de ma form. J'aimerai que cette méthode soit générique : c'est à dire qu size of DATA table et insertion d'une image [ par japouni ] Salut, je veux changer la largeure d'une collone précise par exemple 1 dans mon data table. et je veux introduire une image dans une cellule de mon da Aide pour un zoom [ par DashCash ] Salut à tous! J'aurais besoin d'un ptit coup de main, je dispose d'une Form dans laquelle j'ai créé une PictureBox. Je voudrais simplement pouvoir zo picturebox ou panel , comment faire? [ par panini ] Je suis en train de faire une appli, dans laquelle je dois afficher une image (d'un fichier connu), jusque la pas de pb j'utilise un picturebox avec l Image, flux binaire , redimensionnement [ par Diamondduff ] Je suis un peu perplexe, comment cela fonctionne t-il? quel type de composant il faut pour faire ca?L'image est affichée apparemment par flux, la tail Comment redimensionner une image sans agrandir son contenu [ par taupe4 ] Bonjour, je développe présentement une application de traitement d'images (qui commencera par ressembler à Paint) afin de faire un module pour une app Problème mémoire avec fonction zoom [ par rbidocho ] Bonsoir,Voilà, j'ai un usercontrol qui me trace un graphique que j'insère après dans mon MainForm. Quand je clique sur le graphique je fais un Zoom pa Usage Graphicsstate [ par olibara ] BonsoirEn dessinant sur un picture box, J'essaye de faire quelque chose mais je ne sais pas si c'est possibleEn fait j'essaye de faire DEUX operation


Nos sponsors


Sondage...

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,577 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales