1

我想从stbir_resize_uint8(来自https://github.com/nothings/stb/blob/master/stb_image_resize.h)获得结果,将其压缩为 JPG 并将其存储到缓冲区而不将其保存到磁盘。

我已经得到了结果,stbir_resize_uint8unsigned char*我不知道如何以 JPG 格式获取指向数据的指针。这可以用 stb_image_write.h 完成还是我需要另一个库?

我尝试stbi_write_jpg_to_funchttps://github.com/nothings/stb/blob/master/stb_image_write.h像这样使用。

//图像.h

static unsigned char memoryJPG[32768];
static int thumbSize = 0;

struct ImageInfo
{
    unsigned char* data;
    int size;
};

class Image 
{
    public:
    unsigned char* writeToMemoryAsJPG(const int quality = 90);

    private:
    unsigned char* mImageData = nullptr;
    int mWidth;
    int mHeight;
    int mDepth;
};

//图像.cpp

ImageInfo Image::writeToMemoryAsJPG(const int quality)
{
    auto rv = stbi_write_jpg_to_func([](void *context, void *data, int size)
    {
        if (size > 32768) size = 32768;
        memcpy(memoryJPG, data, size);
        thumbSize = size;
    }, nullptr, mWidth, mHeight, mDepth, mImageData, quality);

    ImageInfo ii;
    ii.data = memoryJPG;
    ii.size = thumbSize;
    return ii;
}

这不会返回任何东西,但即使它确实返回了正确的结果,静态变量也非常难看。我如何在没有任何静态变量的情况下编写此方法?

4

2 回答 2

2

这就是我所做的,但这不是一个好的解决方案,因为如果启用了编译器优化,这可能会出现内存对齐问题,所以如果有人有更好的解决方案,请发布答案。

事实证明我stbi_write_jpg_to_func以错误的方式使用。显然,该函数是按顺序调用的,每次调用它都会从 JPG 中检索一段可变长度的数据。因此,每次调用该函数时,我只需将该段数据添加到内存缓冲区中。像这样的东西:

图像.h

struct ImageData
{
    unsigned char data[32768];
    size_t size = 0;
};

class Image 
{
    public:
    unsigned char* writeToMemoryAsJPG(const int quality = 90);

    private:
    unsigned char* mImageData = nullptr;
    int mWidth;
    int mHeight;
    int mDepth;
};

图像.cpp

ImageData Image::writeToMemoryAsJPG(const int quality)
{
    ImageData ii;
    auto rv2 = stbi_write_jpg_to_func(
        [](void *context, void *data, int size)
        {
            memcpy(((ImageData*)context)->data + ((ImageData*)context)->size, data, size);
            ((ImageData*)context)->size += size;
        }
    ,&ii, mWidth, mHeight, mDepth, mImageData, quality);

    return ii;
}
于 2019-09-12T20:19:13.663 回答
0

我在stbi项目的github页面的issues中找到了一个通用的解决方案

typedef struct {
    int last_pos;
    void *context;
} custom_stbi_mem_context;

// custom write function
static void custom_stbi_write_mem(void *context, void *data, int size) {
   custom_stbi_mem_context *c = (custom_stbi_mem_context*)context; 
   char *dst = (char *)c->context;
   char *src = (char *)data;
   int cur_pos = c->last_pos;
   for (int i = 0; i < size; i++) {
       dst[cur_pos++] = src[i];
   }
   c->last_pos = cur_pos;
}

// get image, width, height and channels

// how to use it:
custom_stbi_mem_context context;
context.last_pos = 0;
context.context = (void *)buffer;

int result = stbi_write_jpg_to_func(custom_stbi_write_mem, &context, width, height, channels, image, WS_JPEG_COMPRESSION);

如果问题被接受,stbi_write_jpg_to_mem可以在标题中添加该功能,检查一下:

https://github.com/nothings/stb/issues/1132

我希望这会有用!

于 2021-05-28T17:02:24.560 回答