Question

I'm having a problem with writing to files using lock bits. I'm working on an edge detection software which has a strange distortion effect with most images. I've tried to isolate the problem, and it seems very random. It is not associated with format, but rather the only images that seem to work are pictures made for desktop wallpapers, and I don't really know why. I only switched to writing to files using lockbits recently, so I am sure the problem is with that (there were no problems when I was reading with lockbits and writing with set pixel). Here's a screenshot of the effect:

Screenshot

As you can see, the edge detection works, but the image is distorted horizontally, making the image into a parallelogram.

Here's a code snippet of the method that handles all this (in C#):

private void analyze()
{
    //When the analyze button is pressed
    percentageInt = float.Parse(textBox1.Text);
    float scale = 1;

    if (comboBox1.SelectedItem == "Auto")
    {
        scale = pic.Width / pictureBox1.Width;
    }
    else if (comboBox1.SelectedItem == "1/2")
    {
        scale = 2;
    }
    else if (comboBox1.SelectedItem == "1/4")
    {
        scale = 4;
    }
    else if (comboBox1.SelectedItem == "Original")
    {
        scale = 1;
    }
    else
    {
        scale = pic.Width / pictureBox1.Width;
    }

    int tempWidth = 1;
    int tempHeight = 1;
    if (scale >= 1)
    {
        tempWidth = (int)Math.Floor(pic.Width / scale);
        tempHeight = (int)Math.Floor(pic.Height / scale);
    }
    else
    {
        tempWidth = pic.Width;
        tempHeight = pic.Height;
    }

    width = pic.Width;
    height = pic.Height;
    edgeData = new Boolean[pic.Width, pic.Height];

    img = (Bitmap)resizeImage(pic, new Size(tempWidth, tempHeight));
    pic2 = new Bitmap(tempWidth, tempHeight);
    Bitmap img2 = (Bitmap)pic2;
    Color[] pixels = null;

    BitmapData data = img.LockBits(new Rectangle(0, 0, img.Width, img.Height),
            ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

    int size = Math.Abs(data.Stride) * img.Height;
    Byte[] bytes = new byte[size];

    int scaledPercent = (int)(Math.Round(percentageInt * 255));
    Debug.WriteLine("percent " + scaledPercent);
    unsafe
    {
        Debug.WriteLine("Woah there, unsafe stuff");
        byte* prevLine = (byte*)data.Scan0;
        byte* currLine = prevLine + data.Stride;
        byte* nextLine = currLine + data.Stride;

        for (int y = 1; y < img.Height - 1; y++)
        {
            byte* pp = prevLine + 3;
            byte* cp = currLine + 3;
            byte* np = nextLine + 3;
            for (int x = 1; x < img.Width - 1; x++)
            {
                if (IsEdgeOptimized(pp, cp, np, scaledPercent))
                {
                    edgeData[x, y] = true;
                    //Debug.WriteLine("x " + x + "y " + y);

                    //img2.SetPixel(x, y, Color.Black);
                    //bytes[(y * img.Width + x) * 3 + 2] = 255;
                }
                else
                {
                    bytes[(y * img.Width + x) * 3] = 255;
                    bytes[(y * img.Width + x) * 3 + 1] = 255;
                    bytes[(y * img.Width + x) * 3 + 2] = 255;
                    //img2.SetPixel(x, y, Color.White);
                }
                pp += 3; cp += 3; np += 3;
            }
            prevLine = currLine;
            currLine = nextLine;
            nextLine += data.Stride;
        }
    }
    System.Runtime.InteropServices.Marshal.Copy(bytes, 0, data.Scan0, size);
    img.UnlockBits(data);
    pictureBox2.Image = img;
} // end analyze

So what is causing the problem, and how can I fix it? If you need more details, feel free to comment.

Was it helpful?

Solution

You're initializing your bytes buffer with stride x height bytes:

int size = Math.Abs(data.Stride) * img.Height;
Byte[] bytes = new byte[size];

But then using the width (instead of stride) when you write to it:

bytes[(y * img.Width + x) * 3] = 255;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top