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,resizedPixels,textureWidth * scale,textureHeight * scale,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内部处理所有内存分配。我错了吗?

解决方法

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


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

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;
}

如果你仔细查看 resize 函数的签名,你会注意到没有传递这样的参数,因此它无法返回内部分配的内存地址。 (unsigned char* output_pixels 而不是 unsigned char** output_pixels)。因此,您必须自己为调整大小的图像分配内存。

我希望这对您将来有所帮助。


文档中有 mention 的内存分配,但据我所知,这是关于执行调整大小所需的分配,与输出无关。