Ниже моя программа. Я пытаюсь применить фильтр оттенков серого, используя класс bitmapdata в Visual C ++. Я получаю AccessViolationException в 11, помеченный комментарием. Я пытался использовать CLR: Safe и CLR: чисто, но бесполезно. В C # это будет решено с помощью небезопасного блока. Какие-либо предложения? Ни одно из других решений по смежным вопросам не сработало.
Bitmap^ bmp = gcnew Bitmap(pictureBox1->Image);
BitmapData^ data = bmp->LockBits(Rectangle(0,0,bmp->Width,bmp->Height), ImageLockMode::ReadWrite, PixelFormat::Format24bppRgb);
int blue=0, green=0, red=0;
System::IntPtr s = data->Scan0;
int* P = (int*)(void*)s;
for (int i =0; i<bmp->Height;i++)
{
for (int j = 0; j < bmp->Width*3; j++)
{
blue = (int)P[0]; //access violation exception
green =(int )P[1];
red = (int)P[2];
int avg = (int)((blue + green + red) / 3);
P[0] = avg;
P[1] = avg;
P[2] = avg;
P +=3;
}
}
bmp->UnlockBits(data);
pictureBox1->Image = bmp;
Вы используете int*
когда вы должны использовать byte*
, Ваши пиксели — три байта каждый, один байт на канал. Ваш int (вероятно) 4 байта, так p[0]
возвращает весь пиксель плюс на байте мимо него. Вот почему вы получаете нарушение доступа; Вы превышаете границы буфера изображения.
Когда вы увеличиваете указатель, вы добавляете sizeof *p
байты к нему. В этом случае, P += 3
увеличивает указатель P
от 12
байт. Слишком много, и вы никогда не сможете прочитать один пиксель (или канал) изображения 24bpp с int*
, Вы также предполагаете, что ваш шаг Width * 3
, что может быть или не быть правильным (битовые карты выровнены на 4 байта).
Byte* base = (Byte*)data->Scan0;
int stride = data->Stride;
for(int y = 0; y < data->Height; ++y) {
Byte* src = base + y * stride;
for(int x = 0; x < data->Width; ++x, src += 3) {
// bitmaps are stored in BGR order (though not really important here).
// I'm assuming a 24bpp bitmap.
Byte b = src[0];
Byte g = src[1];
Byte r = src[2];
int average = (r + g + b) / 3;
src[0] = src[1] = src[2] = (Byte)average;
}
}
Других решений пока нет …