taji01
taji01

Reputation: 2615

Image color invert on button click C#

I'm using WinForms. I got a picturebox which contains an image. On button click I want to invert the colors of this image back and forth. I tried to make the images invert faster by a button click with the code below. The problem I'm having is that I get an error

Error: Where the code says: Parallel.ForEach(rect.SubRectangles <- I get an error: 'Rectangle' does not contain a definition fo subRectangles' and no extension method 'SubRectangles' accepting a first argument of type 'Rectangel' could be found

2nd error: Under the IEnumerable<Rectangle>SubRectangles <--- (Extension)IEnumerable<Rectangle>ImageUtility.SubRectangle(this Rectanger,... Extension methods must be defined in a top level static class; ImageUtility is a nested class.

Another issue I'm having is calling this code into the button click event so it could work. I'm still learning how to program.

public static class ImageUtility
{
public static Bitmap Process(Bitmap bmp)
{
    Bitmap retBmp = new Bitmap(bmp);

    var depth = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8;
    if (depth < 3) throw new ArgumentException("Image must be at least 24 bpp.");

    var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    var data = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);

    var buffer = new byte[data.Width * data.Height * depth];

    //copy pixels to buffer
    Marshal.Copy(data.Scan0, buffer, 0, buffer.Length);
    bmp.UnlockBits(data);

    //Process Image
    Parallel.ForEach(rect.SubRectangles(2, 4), r => InvertColor(buffer, r, data.Width, depth));

    //Copy the buffer back to  image
    data = retBmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);
    Marshal.Copy(buffer, 0, data.Scan0, buffer.Length);
    retBmp.UnlockBits(data);

    return retBmp;
}

static void InvertColor(byte[] buffer, Rectangle r, int orgWidth, int depth)
{
    for (int i = r.X; i < r.X + r.Width; i++)
    {
        for (int j = r.Y; j < r.Y + r.Height; j++)
        { 
            var offset = ((j * orgWidth) + i) * depth;
            buffer[offset + 0] = (byte)(255 - buffer[offset + 0]);
            buffer[offset + 1] = (byte)(255 - buffer[offset + 1]);
            buffer[offset + 2] = (byte)(255 - buffer[offset + 2]);
        }
    }
}

public static IEnumerable<Rectangle> SubRectangles(this Rectangle r, int dx, int dy)
{
    int incX = (r.Width - r.X) / dx;
    int incY = (r.Height - r.Y) / dy;

    for (int y = r.Y; y < r.Height; y += incY)
    {
        for (int x = r.X; x < r.Width; x += incX)
        {
            yield return new Rectangle(x, y, incX, incY);
        }
    }
}
}

    private void button_Color_Invert_Click(object sender, EventArgs e)
    {
     //TO DO:

    }

Upvotes: 0

Views: 560

Answers (1)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112682

Well, it compiles for me. Is your class ImageUtility nested in another class? It shouldn't be, because extension methods must be placed in a top level static class. That's what your second error message is saying. The method SubRectangles is an extension method, because of the this keyword in the parameter list.

class ImageUtility should be placed in its own file.


public static class A // Top level and static
{
    class B // Nested
    {
    }
}

See:
- Static Classes and Static Class Members (C# Programming Guide)
- Extension Methods (C# Programming Guide)

Upvotes: 1

Related Questions