stb_image库加载图片函数研究

目录

1.stbi__start_mem

1.1stbi_load_16_from_memory()

1.2stbi_load_from_memory()

1.3stbi_loadf_from_memory

2.stbi_load_and_postprocess_8bit()

2.1stbi_load_from_file()

2.2stbi_load_from_memory()

3.stbi__start_file

3.1stbi_load_from_file()

4.stbi_load


一个简单易用的图像库:stb_image 。Github 地址为:https://github.com/nothings/stb ,目前已经有了 9600+ Star 。它的使用非常简单,看看 README 可能你就会了。

1.stbi__start_mem

源代码:


// initialize a memory-decode context
static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len)
{
   s->io.read = NULL;
   s->read_from_callbacks = 0;
   s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer;
   s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len;
}

该函数的功能:初始化内存上下文。

1.1stbi_load_16_from_memory()

STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels)
{
   stbi__context s;
   stbi__start_mem(&s,buffer,len);
   return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels);
}

1.2stbi_load_from_memory()

STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
{
   stbi__context s;
   stbi__start_mem(&s,buffer,len);
   return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
}

1.3stbi_loadf_from_memory

STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
{
   stbi__context s;
   stbi__start_mem(&s,buffer,len);
   return stbi__loadf_main(&s,x,y,comp,req_comp);
}

2.stbi_load_and_postprocess_8bit()

static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
{
   stbi__result_info ri;
   void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8);

   if (result == NULL)
      return NULL;

   if (ri.bits_per_channel != 8) {
      STBI_ASSERT(ri.bits_per_channel == 16);
      result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
      ri.bits_per_channel = 8;
   }
// @TODO: move stbi__convert_format to here

   if (stbi__vertically_flip_on_load) {
      int channels = req_comp ? req_comp : *comp;
      stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc));
   }

   return (unsigned char *) result;
}

2.1stbi_load_from_file()

STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
{
   unsigned char *result;
   stbi__context s;
   stbi__start_file(&s,f);
   result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
   if (result) {
      // need to 'unget' all the characters in the IO buffer
      fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
   }
   return result;
}

2.2stbi_load_from_memory()

见1.3

3.stbi__start_file

static void stbi__start_file(stbi__context *s, FILE *f)
{
   stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f);
}

stbi__start_callbacks:

// initialize a callback-based context
static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user)
{
   s->io = *c;
   s->io_user_data = user;
   s->buflen = sizeof(s->buffer_start);
   s->read_from_callbacks = 1;
   s->img_buffer_original = s->buffer_start;
   stbi__refill_buffer(s);
   s->img_buffer_original_end = s->img_buffer_end;
}

3.1stbi_load_from_file()

见2.1

4.stbi_load

STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp)
{
   FILE *f = stbi__fopen(filename, "rb");
   unsigned char *result;
   if (!f) return stbi__errpuc("can't fopen", "Unable to open file");
   result = stbi_load_from_file(f,x,y,comp,req_comp);
   fclose(f);
   return result;
}

该函数是darknet框架中load_image_stb()中调用的函数,给定文件名。调用流程如下:

1).load_image_color中调用load_image()

image load_image_color(char *filename, int w, int h)
{
    return load_image(filename, w, h, 3);
}

2).load_image中调用load_image_std()我们看到参数c=3

image load_image(char *filename, int w, int h, int c)
{
#ifdef OPENCV
    //image out = load_image_stb(filename, c);
    image out = load_image_cv(filename, c);
#else
    image out = load_image_stb(filename, c);    // without OpenCV
#endif  // OPENCV

3).load_image_std()中调用stbi_load(),从1)和2)可以看出,channels=3

image load_image_stb(char *filename, int channels)
{
    int w, h, c;
    unsigned char *data = stbi_load(filename, &w, &h, &c, channels);

4.从stbi_load()函数代码可以看出,x,y,comp是需要传出的宽,高和通道,

STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp)
{
   FILE *f = stbi__fopen(filename, "rb");
   unsigned char *result;
   if (!f) return stbi__errpuc("can't fopen", "Unable to open file");
   result = stbi_load_from_file(f,x,y,comp,req_comp);
   fclose(f);
   return result;
}

darknet改成从内存中读取图片,可以将stbi_load_form_file()改成stbi_load_from_memory()

对比stbi_load_from_file()(见2.1)和stbi_load_from_memory()(见1.3)函数,后面四个参数都相同,唯一不同的是第一个参数:

stbi_load_from_memory()函数的第一个参数为:

stbi_uc const *buffer

stbi_uc本质上实际上是一个unsigned char类型,其定义如下:

typedef unsigned char stbi_uc;

也就是说直接传入内存中图片地址就可以了,比从从文件流中加载图片更加简单。

但是有个前提,就是传给stbi_load_from_memory的内存的图片数据存储格式因给同stbi_load_from_file读进来的一样才行,否则分类结果难以想象。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
使用 stb_image.h 读取材质可以让我们很方便地加载各种格式的图片,这里以 OpenGL 中的纹理为例进行说明。首先需要下载 stb_image.h ,并将其添加到项目中。 使用 stb_image.h 加载纹理的一般步骤如下: 1. 使用 `glGenTextures` 函数生成一个纹理 ID。 2. 使用 `glBindTexture` 函数将纹理 ID 绑定到目标纹理类型上,例如 `GL_TEXTURE_2D`。 3. 使用 `stbi_load` 函数加载图片数据,并获取图片的宽度、高度和颜色通道数。 4. 使用 `glTexImage2D` 函数图片数据传递给 OpenGL,生成纹理。 5. 使用 `glTexParameteri` 函数设置纹理的参数,例如过滤方式和环绕方式。 6. 释放图片数据。 加载纹理的代码示例如下: ```c++ // 读取图片 int width, height, nrChannels; unsigned char *data = stbi_load("texture.jpg", &width, &height, &nrChannels, 0); // 创建纹理对象 unsigned int texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); // 设置纹理参数 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 生成纹理 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); // 释放图片数据 stbi_image_free(data); ``` 注意:在使用 stb_image.h 加载纹理时,需要将图片的 y 轴翻转,否则加载出来的纹理会是倒置的。可以通过设置 `stbi_set_flip_vertically_on_load(true)` 来实现自动翻转。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

haimianjie2012

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值