Estomper couleurs image en compact framework [Résolu]

Signaler
Messages postés
223
Date d'inscription
mercredi 31 mai 2006
Statut
Membre
Dernière intervention
5 mai 2014
-
Messages postés
1137
Date d'inscription
lundi 17 novembre 2003
Statut
Membre
Dernière intervention
23 janvier 2016
-
Bonjour,

Sur une cible windows Ce 6.0 sans chipset graphique , je cherche à estomper progressivement les couleurs d'une image de manière performante .
Cette image est en mémoire dans un objet Bitmap.

J'ai pondu ce bout de code, mais ce n'est pas performant du tout ...
Quelqu'un aurait-il une meilleure idée ?

Merci

            _original = (Bitmap)Original.Image;
            _resultat = new Bitmap(_original.Width, _original.Height);
    Color pixelL;
            Color pixelFinalL = new Color();
            for (int x = 0; x < _original.Width; x++)
            {
                for (int y = 0; y < _original.Height; y++)
                {
                    pixelL = _original.GetPixel(x, y);
                    switch (_etape)
                    {
                        case 0:
                            pixelFinalL = pixelL;
                            break;

                        case 5:
                            pixelFinalL = Color.FromArgb(255, 255, 255);
                            break;

                        default:
                            pixelFinalL = Color.FromArgb(pixelL.R + ((255 - pixelL.R) * _etape) / 5, pixelL.G + ((255 - pixelL.G) * _etape) / 5, pixelL.B + ((255 - pixelL.B) * _etape) / 5);
                            break;
                    }
                    _resultat.SetPixel(x, y, pixelFinalL);
                }
            }

3 réponses

Messages postés
1137
Date d'inscription
lundi 17 novembre 2003
Statut
Membre
Dernière intervention
23 janvier 2016
18
Salut,

tu peux passer par du code "non managé",
qui donne les meilleures perf. pour ce genre de fonction d'accès aux pixels :

[StructLayout(LayoutKind.Sequential)]
public struct BGR
{
    public byte blue;
    public byte green;
    public byte red;
    public byte alpha;
};

private void process(ref Bitmap img, int etape)
{
    BitmapData bmpData = null;

    try
    {
        Rectangle rcEffect = new Rectangle(0, 0, img.Width, img.Height));

        bmpData = img.LockBits(
            rcEffect,
            ImageLockMode.ReadWrite,
            PixelFormat.Format32bppArgb);

        Color tmpClr;

        unsafe
        {
            BGR* pixel = (BGR*)bmpData.Scan0;
            for (int x = 0; x < rcEffect.Width; x++)
            {
                for (int y = 0; y < rcEffect.Height; y++)
                {
                    tmpClr = Color.FromArgb(
                        pixel->alpha,
                        pixel->red,
                        pixel->green,
                        pixel->blue);

                    switch (etape)
                    {
                        case 0:
                            break;
                        case 5:
                            pixel->red 0xff; pixel->green 0xff; pixel->blue = 0xff; 
                            break;
                        default:
                            pixel->red = (byte)(tmpClr.R + ((255 - tmpClr.R) * etape) / 5);
                            pixel->green = (byte)(tmpClr.G + ((255 - tmpClr.G) * etape) / 5);
                            pixel->blue = (byte)(tmpClr.B + ((255 - tmpClr.B) * etape) / 5);
                            break;
                    }

                    pixel++;
                }
            }
        }
    }
    catch (Exception exc)
    {
        
    }
    finally
    {
        if (bmpData != null)
        {
             img.UnlockBits(bmpData);
        }
    }
}


J'imagine que tu utilises ça dans une boucle

//debut boucle
_resultat = new Bitmap(_original.Width, _original.Height);
process(ref _resultat, 1);
PictureBox1.Image = _resultat;
// fin boucle

bye...
Messages postés
223
Date d'inscription
mercredi 31 mai 2006
Statut
Membre
Dernière intervention
5 mai 2014

Super ! merci.
C'est finalement ce que j'ai fais, et c'est beaucoup plus performant (de 40s je passe à environ 1s de temps dans la boucle).

Une petite question supplémentaire car je vois que tu es calé sur le sujet :
Je voudrais que cet algo fonctionne sur l'ensemble de l'écran. Autrement dit, je voudrais pouvoir modifier directement la "mémoire vidéo".
Aurais tu une solution pour récupérer un buffer des pixels de l'écran, les modifier via l'algo, et les réaffecter sur l'écran ?

Une idée consisterai à parcourir les Controls de l'IHM, mais j'aimerais une meilleure solution.

Merci par avance



 
Messages postés
1137
Date d'inscription
lundi 17 novembre 2003
Statut
Membre
Dernière intervention
23 janvier 2016
18
Re,

Déjà tu peux faire un "PrintScreen" afin d'avoir l'écran dans un bitmap.

public static Bitmap GetScreenShot(int screenWidth, int screenHeight, bool bWithCursor)
{
    Graphics g = null;
    try
    {
        Bitmap printscreen = new Bitmap(screenWidth, screenHeight);
        g = Graphics.FromImage(printscreen as Image);
        g.CopyFromScreen(
            0,
            0,
            0,
            0,
            printscreen.Size);

        if (bWithCursor) /*ajoute le curseur de la sourie*/
        {
            Rectangle cursorBounds = new Rectangle(Cursor.Position, Cursor.Current.Size);
            Cursors.Default.Draw(g, cursorBounds);
        }
        return printscreen;
    }
    catch (Exception)
    {
        return null;
    }
    finally
    {
        if (g != null)
            g.Dispose();
    }
}


Ensuite, tout dépend du contexte,
une solution simple est de "dessiner" ce bitmap dans la fenetre principale de ton programme en mode "plein écran", ce qui simulera le bureau entier.

Pour passer ta fenetre principale en plein écran, il suffit d'enlever les barres de titre et d'outil et de la localiser sur la taille de l'écran en position 0,0.

bye...