1

嘿,所以我正在尝试制作一个接收图像参考和 sf::IntRect 的函数

这有 4 个整数代表一个矩形的顶部、底部、左侧和右侧。这个矩形代表正在显示的图像的一部分,但实际上并没有切断矩形之外的像素)

然后通过切断 IntRect 之外的像素创建一个新的压缩图像。我想我能做到这一点的唯一方法是制作一个与 IntRect 尺寸相同的 2d 像素数组,然后通过迭代图像来填充它,但由于我不知道 IntRect 的尺寸,我无法制作一个常数大批......

这个问题不断出现,我认为对 c_style 数组进行大量矢量工作和转换会花费很多性能..

是否有一些简单的解决方案来大量操作/更改图像的尺寸和颜色?

4

1 回答 1

1

存储和访问二维图像(或任何可变大小的二维矩阵)的常用方法是分配一个合适大小的一维数组(width * height(width + padding) * height),并“手动”计算数组的索引(y * stride + x,在哪里stridewidth + padding

(我通常std::vector用于那个一维数组,但那是另一回事)

引用 2D 图像数据的常用方法(在传递引用中引用)是传递一个元组:

  • void* imageData-- 左上角像素的地址
  • size_t strideimageData-- 要添加到下一行的字节数
  • size_t width
  • size_t height
  • SomeEnum pixelFormat-- 图片的像素格式(如果只有一个可以省略)

当然,如果只有一种 Pixel-Format,您可以使用类型化指针,并指定该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指向子矩形的左上角像素并设置子矩形widthheight宽度和高度。stride保持不变。

这意味着您不必“具体化”裁剪的图像,您只需将对子矩形的引用传递给任何函数,它将像在“完整”图像上一样对该子矩形进行操作。

而且,如果您真的想“实现”裁剪后的图像,那么您现在也应该有足够的信息来做到这一点。至少我希望如此:)

编辑:由于您对 sf::IntRect 部分非常明确,但后来只写了“image”而不是 sf::Image,我假设您在谈论您自己管理的东西,而不是 sf::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);
于 2011-06-15T01:17:04.933 回答