странное поведение ошибки «Попытка чтения или записи в защищенной памяти» - PullRequest
0 голосов
/ 24 марта 2012

У меня есть метод в моей программе C # WinForms, который проверяет, есть ли в столбце X изображения черные пиксели или нет.

    static Boolean GetColumnState(Bitmap bmp, int x, int col)
    {
        BitmapData pixelData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);
        Boolean state = false;
        unsafe
        {
            int* pData = (int*)pixelData.Scan0.ToPointer();
            pData += x;
            for (int i = 0; i < bmp.Height; ++i)
            {
                pData += bmp.Width;
                if (Color.FromArgb(*pData) == Color.FromArgb(255, col, col, col)) // error here
                { state = true; break; }
            }
        }
        bmp.UnlockBits(pixelData);
        return state;
    }

К сожалению, я получаю

«Попытка чтения или записи в защищенную память» Ошибка

at "(Color.FromArgb (* pData) == Color.FromArgb (255, col, col, col))" line

Вот как я определяю «col» из другого метода:

           if (GetColumnState(b1, 0, 255) == false)
            { col = 255; }
           else {col = 0;}
           // more code + loops
           GetColumnState(b1, i, col)

Странная вещь: я получаю ошибки, только если цвет пикселя определен как 255 (т.е. черный) ..

Как вы это объясните? Обратите внимание, что я пишу программу распознавания текста, поэтому загружаю несколько словарей с разными значениями ключей. Я много обрезаю изображения во время распознавания. Мое счастливое предположение, что потоки портят друг друга.

Теперь я нашел способ исправить эту проблему, но цена составляет + ~ 150-200мс к общему времени выполнения скрипта (я думаю, что это ненужная цена).

Обычно я загружаю словари вот так:

        Dictionary<string, Bitmap> lookup = new Dictionary<string, Bitmap>();
        Bitmap l0 = new Bitmap(@"C:\xxx\0.bmp", true);
            //+15 more
        lookup.Add("0", l0);
            //+15 more

        Dictionary<string, Bitmap> lookup2 = new Dictionary<string, Bitmap>();
        Bitmap nAa = new Bitmap(@"C:\yyy\Aa.bmp", true);
            //+15 more
        lookup2.Add("A", nAa);
            //+15 more

Чтобы решить эту проблему, я должен создать «пустоты» для каждого словаря и загрузить их в разные потоки, например:

void loadNumbers1()
{
        lookup4 = new Dictionary<string, Bitmap>();
        Bitmap sd = new Bitmap(@"C:\xxxxx\a.bmp", true);
            //+15 more
        lookup4.Add("0", s0);
            //+15 more
}

void loadNumbers2()// 4, 5, 6,
{
        //repeat
}

Теперь мы запускаем темы:

        Thread tNum2= new Thread(new ThreadStart(loadNumbers2));
        tNum2.Start();

        Thread tNum3= new Thread(new ThreadStart(loadNumbers3));
        tNum3.Start();

Последний шаг ( без этого шага программа работает быстрее, но ошибка возникает чаще ):

tNum3.Join();

Вот и все, теперь у меня нет проблем, но время выполнения больше .. Есть идеи, как решить эту проблему более простым способом, без использования нескольких потоков? В моем случае без join () я получаю 5-100мс время загрузки словаря, с join () - до 300мс. Без потоков - до 180 (в случае, если ошибка не возникает).

Извините за длинный пост

РЕДАКТИРОВАТЬ: (постоянное исправление)

static unsafe Boolean GetColumnState(Bitmap bmp, int x, int col)
        {
            BitmapData pixelData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);
            Boolean state = false;

            unsafe
            {
                byte[] buffer = new byte[pixelData.Height * pixelData.Stride];
                Marshal.Copy(pixelData.Scan0, buffer, 0, buffer.Length);

                for (int i = 0; i < pixelData.Height - 1; ++i)
                {
                    byte red = buffer[i * pixelData.Stride + 4 * x + 2];
                    if (red == col)
                    { state = true; break; }
                }
            }
            bmp.UnlockBits(pixelData);
            return state;
        }

Я не понимаю, что такого плохого в указателях, но байты работают отлично. @ tia спасибо за указание на мою проблему.

Кто-нибудь знает, почему многопоточность замедляет время загрузки словаря, а не ускоряет его?

1 Ответ

1 голос
/ 24 марта 2012

Если я правильно понимаю код, цикл

for (int i = 0; i < bmp.Height; ++i)
{
    pData += bmp.Width;
    if (Color.FromArgb(*pData) == Color.FromArgb(255, col, col, col)) // error here
    { state = true; break; }
}

не правильно. Указатель должен быть увеличен в конце итерации, иначе вы пропустите первую строку сканирования и переполнитесь чтением буфера растрового изображения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...