Считывание пикселей из SDL_Surface и преобразование в значения цвета

#c #2d #sdl #pixel #alpha

#c #2d #sdl #пиксель #альфа

Вопрос:

Я действительно не знаю, что не так (в основном потому, что я не знаю, что делает строка, которая выдает мне ошибку).

Я не думаю, что мне нужно показывать вам так много кода. Что я делаю, так это то, что я пытаюсь получить значения RGBA пикселя, чтобы увидеть, насколько велико альфа-значение. Я использую это, чтобы определить, есть ли столкновение внутри их прямоугольников или нет.

Это то, что у меня есть:

 bool Texture2D::GetPixelAlphaValue(Vector2 pixel)
{
int bpp = surface->format->BytesPerPixel;
Uint8* p = (Uint8*) surface->pixels   (int) pixel.y * surface->pitch   (int) pixel.x * bpp);

Uint32 pixelColor = *(Uint32*)p;

Uint8 red, green, blue, alpha;
SDL_GetRGBA(pixelColor, surface->format, amp;red, amp;green, amp;blue, amp;alpha);

return alpha > 250;
}
  

Я почти уверен, что мое столкновение подходит для этого, что я делаю, я проверяю, пересекается ли прямоугольник, я создаю прямоугольник пересечения, а затем проверяю каждый пиксель внутри пересекающегося прямоугольника.

Это приводит к тому, что как только у меня на экране возникает идеальное пиксельное столкновение, игра вылетает, и я получаю стрелку, указывающую на:

 Uint32 pixelColor = *(Uint32*)p;
  

С ошибкой:

  Unhandled exception at 0x000393b4 in OpenGLSDLTest.exe: 0xC0000005: Access violation      reading location 0x063b6fd0.
  

Это строка, которую я не понимаю, может кто-нибудь, пожалуйста, объяснить, что делает эта строка и как я могу это решить?

С уважением

Markus

Комментарии:

1. Это действительно ваш реальный код? Потому что я удивлен, что это вообще компилируется. В строке 4 указателю на Uint8 присваивается целое число.

2. p перепрыгивает через surface-> pixels?

3. Ваш код выглядит очень похоже на это: Pixel_Access Вы сначала заблокировали surface, как указано, что вам нужно? В вашем коде также есть ошибка, если сравнивать с кодом примера. Вы хотите преобразовать surface-> pixels в a (Uint8*), а не a (Uint8).

4. Извините, вы правы, я пропустил *, когда писал вопрос, он есть в моем коде.

5. Подсказка: обычно лучше всего использовать копирование / вставку из фактического кода. Таким образом, вы не добавляете новых ошибок (или, в крайнем случае, даже случайно исправляете фактическую ошибку, оставляя кого-либо в недоумении, что должно быть не так с вашим кодом).

Ответ №1:

Нарушение доступа означает, что вы пытаетесь получить доступ к памяти, которая вам не принадлежит. В этом случае вы, вероятно, вызвали эту функцию с x или y вне диапазона (больше, чем размер изображения, или отрицательный).

Вы должны проверить значения x и y , прежде чем выполнять с ними арифметику указателя, тогда вы сможете обработать эту ошибку более изящно (что может означать просто сообщение о том, какое значение было неправильным, а затем прерывание в любом случае, или это может означать сообщение об этой ошибке обратно вызывающему).

Другой возможный источник ошибки находится в строке he, где возникает ошибка. Это переосмысливает указатель на Uint8 как указатель на Uint32 и разыменовывает его. По сути, он считывает четыре байта, относящиеся к этому адресу, в pixelcolor . Обратите внимание, что это приведение допустимо, только если bpp равно 4, и, кроме того, массив пикселей выровнен соответствующим образом для UInt32. Проблема с выравниванием вряд ли вызовет ошибку на платформах на базе x86 (x86 обычно приводит к снижению производительности только для смещенных указателей), но проблема с bpp может возникнуть в конце массива. Чистым (но обычно более медленным) способом было бы читать байты отдельно и составлять их, используя битовые сдвиги, следующим образом:

 UInt32 pixelcolor = 0;
for (int i = 0; i < bpp;   i)
{
  pixelcolor <<= 8;
  pixelcolor  = *p  ;
}
  

Комментарии:

1. Хм, все, что я могу сказать, это то, что ошибка возникает только в том случае, если оба пиксельных цвета не являются 255 альфа. Я пробовал проверять x и y, но это не имеет никакого значения.