首页 > 解决方案 > stbir_resize_uint8 在内存访问时崩溃

问题描述

我正在使用 stb_image 将图像上传到 GPU。如果我只是使用 stbi_load 上传图像,我可以确认(nvidia Nsight)图像已正确存储在 GPU 内存中。但是,我喜欢在上传到 GPU 之前调整一些图像的大小。在这种情况下,我会崩溃。这是代码:

    int      textureWidth;
    int      textureHeight;
    int      textureChannelCount;
    stbi_uc* pixels = stbi_load(fullPath.string().c_str(), &textureWidth, &textureHeight, &textureChannelCount, STBI_rgb_alpha);

    if (!pixels) {
        char error[512];
        sprintf_s(error, "Failed to load image %s!", pathToTexture);
        throw std::runtime_error(error);
    }

    stbi_uc* resizedPixels = nullptr;
    uint32_t imageSize     = 0;
    if (scale > 1.0001f || scale < 0.9999f) {
        stbir_resize_uint8(pixels, textureWidth, textureHeight, 0, resizedPixels, textureWidth * scale, textureHeight * scale, 0, textureChannelCount);
        stbi_image_free(pixels);
        textureWidth *= scale;
        textureHeight *= scale;
        imageSize = textureWidth * textureHeight * textureChannelCount;
    } else {
        resizedPixels = pixels;
        imageSize     = textureWidth * textureHeight * textureChannelCount;
    }

    // Upload the image to the gpu

当此代码在规模设置为 的情况下运行时1.0f,它可以正常工作。但是,当我将比例设置为 时0.25f,程序在方法中崩溃stbir_resize_uint8。我在这两种情况下提供的图像都是1920x1080 RGBA PNG. Alpha 通道设置为1.0f横跨整个图像。

我必须使用哪个函数来调整图像大小?

编辑:如果我自己分配内存,该函数不再崩溃并且工作正常。但我虽然 stb 在内部处理所有内存分配。我错了吗?

标签: stb-image

解决方案


我看到您在编辑中发现并解决了问题,但无论如何这里有一些有用的建议:


似乎源代码(也是文档)中的注释没有明确提到您必须为调整大小的图像分配内存,但是当您仔细查看函数的签名时就会清楚:

STBIRDEF int stbir_resize_uint8(     const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
                                           unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
                                     int num_channels);

想想你自己将如何返回你在函数中分配的内存块的地址。最简单的方法是直接返回指针,如下所示:

unsigned char* allocate_memory( int size )
{ return (unsigned char*) malloc(size); }

但是,返回似乎是为错误代码保留的,因此您唯一的选择是将指针作为副作用进行操作。为此,您需要将指针传递给它(指向指针的指针):

int allocate_memory( unsigned char** pointer_to_array, int size )
{
    *pointer_to_array = (unsigned char*) malloc(size);
    /* Check if allocation was successful and do other stuff... */
    return 0;
}

If you take a closer look at the resize function's signature, you'll notice that there's no such parameter passed, so there's no way for it to return the address of internally allocated memory. (unsigned char* output_pixels instead of unsigned char** output_pixels). As a result, you have to allocate the memory for the resized image yourself.

I hope this helps you in the future.


There is a mention of memory allocation in the docs but as far as I understand, it's about allocations required to perform the resizing, which is unrelated to the output.


推荐阅读