Estomper couleurs image en compact framework

Résolu
Moomoon07 Messages postés 223 Date d'inscription mercredi 31 mai 2006 Statut Membre Dernière intervention 5 mai 2014 - 14 févr. 2013 à 14:31
yann_lo_san Messages postés 1137 Date d'inscription lundi 17 novembre 2003 Statut Membre Dernière intervention 23 janvier 2016 - 15 févr. 2013 à 14:03
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

yann_lo_san Messages postés 1137 Date d'inscription lundi 17 novembre 2003 Statut Membre Dernière intervention 23 janvier 2016 26
15 févr. 2013 à 00:46
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...
1
Moomoon07 Messages postés 223 Date d'inscription mercredi 31 mai 2006 Statut Membre Dernière intervention 5 mai 2014
15 févr. 2013 à 12:31
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



 
0
yann_lo_san Messages postés 1137 Date d'inscription lundi 17 novembre 2003 Statut Membre Dernière intervention 23 janvier 2016 26
15 févr. 2013 à 14:03
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...
0
Rejoignez-nous