У меня есть массив пикселей, хранящихся в векторе следующим образом:
typedef union RGBA
{
std::uint32_t Colour;
struct
{
std::uint8_t R, G, B, A;
};
} *PRGB;
std::vector<RGBA> Pixels; //My pixels are read into this vector.
Я обрабатываю его, используя следующие две функции. Один для чтения, другой для письма.
Функция чтения берет массив байтов, переворачивает их и сохраняет их в структуре выше. Он учитывает отступы, поэтому работает как с 24-, так и с 32-битными растровыми изображениями. Функция write переворачивает его и записывает в массив байтов.
void ReadPixels(const std::uint8_t* In, RGBA* Out)
{
for (std::size_t I = 0; I < height; ++I)
{
for (std::size_t J = 0; J < width; ++J)
{
Out[(height - 1 - I) * width + J].B = *(In++);
Out[(height - 1 - I) * width + J].G = *(In++);
Out[(height - 1 - I) * width + J].R = *(In++);
Out[(height - 1 - I) * width + J].A = (BitsPerPixel > 24 ? * (In++) : 0xFF);
}
if(BitsPerPixel == 24)
In += (-width * 3) & 3;
}
}
void WritePixels(const RGBA* In, std::uint8_t* Out)
{
for (std::size_t I = 0; I < height; ++I)
{
for (std::size_t J = 0; J < width; ++J)
{
*(Out++) = In[(height - 1 - I) * width + J].B;
*(Out++) = In[(height - 1 - I) * width + J].G;
*(Out++) = In[(height - 1 - I) * width + J].R;
if (BitsPerPixel > 24)
*(Out++) = In[(height - 1 - I) * width + J].A;
}
if(BitsPerPixel == 24)
Out += (-width * 3) & 3;
}
}
Дело в том, что если я хочу изменить только один пиксель в массиве, я должен перевернуть и скопировать все изображение в вектор, изменить пиксель с помощью:
inline void SetPixel(int X, int Y, std::uint32_t Color)
{
Pixels[Y * width + X].Colour = Color;
}
А затем переверните его обратно в массив. Есть ли лучший способ изменить один пиксель в массиве без необходимости делать это каждый раз?
Я попробовал эту формулу (чтобы учитывалось заполнение):
ByteArray[((height - 1 - Y) * width + X) + (Y * ((-width * 3) & 3))] = Color;
Но это не работает. Есть идеи?
Ваш индекс-> индекс формулы выглядит все неправильно.
Может быть:
int stride = width * BitsPerPixel/8;
stride = ((stride - 1) & ~3) + 4; // round up to multiple of 4 bytes
RGBQUAD& selected_pixel = *reinterpret_cast<RGBQUAD*>(array + stride * (height - 1 - Y)) + X * BitsPerPixel/8);
selected_pixel.R = ...
...
Других решений пока нет …