目录
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 可能你就会了。
源代码:
// 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;
}
该函数的功能:初始化内存上下文。
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);
}
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);
}
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);
}
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;
}
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;
}
见1.3
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;
}
见2.1
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读进来的一样才行,否则分类结果难以想象。