Обычным способом хранения и доступа к 2-мерным изображениям (или любой 2-мерной матрице с переменным размером) является выделение 1-мерного массива подходящего размера (width * height
или (width + padding) * height
) и вычислениеиндекс в массив «вручную» (y * stride + x
, где stride
- width + padding
).
(я обычно использую std::vector
для этого одномерного массива, но это другая история)
Обычный способ ссылки на данные двумерного изображения (ссылка как при передаче по ссылке) заключается в передаче кортежа из:
void* imageData
- адреса верхнего-пиксель size_t stride
- количество байтов, добавляемых к imageData
для перехода к следующей строке size_t width
size_t height
SomeEnum pixelFormat
- пиксельный формат изображения (может быть пропущен, если есть только один)
Конечно, если есть только один Pixel-формат, вы можете использоватьвведите указатель и укажите stride
в единицах этого типа (вместо байтов).
Используя такую ссылку, вы можете легко получить доступ к пикселям в цикле и выйтиЭффективность:
size_t const bytesPerPixel = GetBytesPerPixel(ref->pixelFormat);
for (size_t y = 0; y < ref->height; y++)
{
unsigned char* currentLine =
static_cast<unsigned char*>(ref->imageData) + ref->stride * y;
for (size_t x = 0; x < ref->width; x++)
{
// any modern compiler will optimize the multiplication below to
// an incremental addition
unsigned char* currentPixel = currentLine + bytesPerPixel * y;
// do something to the pixel data at
// currentPixel[0] ... currentPixel[bytesPerPixel - 1]
}
}
Хорошая особенность передачи ссылок на изображения таким образом заключается в том, что вы всегда можете «настроить» такую ссылку, чтобы она указывала на подстроку исходного изображения.Вам просто нужно соответствующим образом изменить значения: установите imageData
на верхний левый пиксель подчиненного прямоугольника и установите width
и height
на ширину и высоту подчиненного прямоугольника.stride
остается прежним.
Это означает, что вам не нужно «материализировать» обрезанное изображение, вы можете просто передать ссылку на подчиненный объект любой функции, и он будет работать на этом подчиненном элементе.-корректируйте так же, как это было бы для «полного» изображения.
И если вы действительно хотите «материализовать» обрезанное изображение, у вас теперь должно быть достаточно информации, чтобы сделать это тоже.По крайней мере, я на это надеюсь:)
РЕДАКТИРОВАТЬ: Так как вы были очень откровенны в отношении части sf :: IntRect, но потом написали «image» вместо sf :: Image, я предположилВы говорили о чем-то, чем управляете сами, а не о сфинитере. Image.Ну что ж ...
Если вы просто хотите скопировать вложенный элемент sf :: Image в другой sf :: Image, вы можете просто сделать это:
sf::Image sourceImage = ...;
sf::IntRect subRect = ...;
// construct an empty sf::Image with the appropriate dimensions
sf::Image newImage(subRect.GetWidth(), subRect.GetHeight());
// copy the pixel data into the new image
newImage.Copy(sourceImage, 0, 0, subRect);