Avatar billede kewl Nybegynder
16. maj 2007 - 00:45 Der er 7 kommentarer og
1 løsning

Ændre farve i et billede

Hejsa Eksperter

Jeg har brug for en funktion som kan ændre alle pixels som er mindre end 4 (Se eksempel)

Min funktion virker MEN! det tager en krig at ændre farverne i et billede som er 1920x1200 pixel :(

Findes der ikke en bedere måde at gøre dette på?

------------ Funktion til at ændre farve ------------------

public Bitmap ChangeColor(Bitmap OrgImg)
{
    Bitmap img1 = new Bitmap(OrgImg);
    int x, y;
    // Loop through the OrgImg pixels to change the color.
    for (x = 0; x < img1.Width; x++)
    {
        for (y = 0; y < img1.Height; y++)
        {
            Color newColor;
            Color pixelColor = img1.GetPixel(x, y);
            if ((pixelColor.R <= (byte)4) | (pixelColor.G <= (byte)4) | (pixelColor.B <= (byte)4))
            {
                newColor = Color.FromArgb(255, 255, 255);
                img1.SetPixel(x, y, newColor);
            }
            else
            {
                img1.SetPixel(x, y, pixelColor);
            }
        }
    }
    return img1;
}
Avatar billede bitmatic Nybegynder
16. maj 2007 - 10:14 #1
Du kunne starte med at fjerne unødig kode, og flytte alt det der er fælles for hver pixel ud af loopet.

public Bitmap ChangeColor(Bitmap OrgImg)
{
    Bitmap img1 = new Bitmap(OrgImg);
    int x, y;
    Color newColor = Color.FromArgb(255, 255, 255);
    Color pixelColor;
    byte b = 4;

    // Loop through the OrgImg pixels to change the color.
    for (x = 0; x < img1.Width; x++)
    {
        for (y = 0; y < img1.Height; y++)
        {
            pixelColor = img1.GetPixel(x, y);
            if ((pixelColor.R <= b | (pixelColor.G <= b | (pixelColor.B <= b)
            {
                img1.SetPixel(x, y, newColor);
            }
        }
    }
    return img1;
}

Prøv at se om det hjælper lidt. Det skal lige siges at jeg ikke har prøvet at kompile koden, så jeg tør ikke garantere at det virker :)

/Jakob
Avatar billede crazysnap Seniormester
16. maj 2007 - 10:20 #2
Hej kewl,


Grunden til at det går så langsomt er at GetPixel og SetPixel er meget langsomme metoder til entry i bitmaps. Du kan i stedet bruge unsafe code og tilgå pixel- værdierne direkte ved hjælp af pointers. På den måde slipper du for den store overhead af GetPixel og SetPixel. Jeg har lavet et eksempel til dig nedenfor som udfører den handling du ønsker:


public Bitmap ChangeColor(Bitmap bmSource)
{
    int Width = bmSource.Width;
    int Height = bmSource.Height;

    //Clone bitmap
    Bitmap bmOutput = bmSource.Clone(new Rectangle(0, 0, Width, Height), System.Drawing.Imaging.PixelFormat.Format32bppRgb);

    // Lock the bitmap bits to memory
    System.Drawing.Imaging.BitmapData destData = bmOutput.LockBits(new Rectangle(0, 0, Width, Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppRgb);

    unsafe
    {
        byte* pDest = (byte*)destData.Scan0.ToPointer();

        for (int x = 0; x < Width; x++)
        {
            for (int y = 0; y < Height; y++)
            {
                int r = pDest[((y * Width + x) * 4) + 2];
                int g = pDest[((y * Width + x) * 4) + 1];
                int b = pDest[((y * Width + x) * 4)];

                if (r < (byte)4 || g < (byte)4 || b < (byte)4)
                    r = g = b = 255;

                pDest[((y * Width + x) * 4) + 2] = (byte)r;  //R
                pDest[((y * Width + x) * 4) + 1] = (byte)g;  //G
                pDest[((y * Width + x) * 4)] = (byte)b;    //B

            }
        }
        bmOutput.UnlockBits(destData);
    }

    return bmOutput;
}



Mvh.


- Snap :)
Avatar billede crazysnap Seniormester
16. maj 2007 - 10:41 #3
Hej kewl,


Jeg testede lige hastighedsforskellen mellem den lettere optimerede metode fra bitmatic og min der bruger pointers med et billede på 1280x960:


ChangeColor normal  :  46.615 sek.
ChangeColor pointers :    0.045 sek.


Så der kan man tydeligt se hvor langsomme GetPixel og SetPixel er. :(  Og jeg er faktisk overrasket over de er SÅ langsomme at bruge, troede kun der var en faktor 10 i forskel, men det er jo nærmere en faktor 1000. Så jeg kan godt forstå du brokker dig over hastigheden når du kører metoden på et billede af størrelse 1920x1200. :/


Mvh.

- Snap :)
Avatar billede bitmatic Nybegynder
16. maj 2007 - 10:46 #4
hehe...

Ok. Jeg trækker mig bare fra diskussionen :-)
Avatar billede bitmatic Nybegynder
16. maj 2007 - 10:48 #5
Og så er det jo en herlig chance for lidt pointer-gymnastik.

Det savner man jo næsten i C#.
Avatar billede crazysnap Seniormester
16. maj 2007 - 11:08 #6
Jeg er ihvertfald glad for at C# supporter pointers via unsafe coding, gør mange små-ting en del nemmere og hurtigere. :)

Men anyways, lige en bemærkning til kewl, husk at checke "Allow unsafe code" i "project properties -> Build" for at kunne få lov til at compile min metode og alt andet unsafe kode. :)


Mvh.

- Snap
Avatar billede kewl Nybegynder
16. maj 2007 - 11:21 #7
Crazysnap Nice, 1000 tak virker perfekt!

Smider du lige et svar
Avatar billede crazysnap Seniormester
16. maj 2007 - 11:37 #8
Hej kewl,


Det var så lidt (og godt at høre det virker), og svaret kommer her! :)


Mvh.

- Snap
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester