博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[编程开发]STB image读取学习
阅读量:5292 次
发布时间:2019-06-14

本文共 5067 字,大约阅读时间需要 16 分钟。

为了便于学习图像处理并研究图像算法,

俺写了一个适合初学者学习的小小框架。

 

麻雀虽小五脏俱全。

 

采用的加解码库:stb_image

官方:http://nothings.org/

 

stb_image.h用于解析图片格式:

JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC

stb_image_write.h用于保存图片格式:

PNG, TGA, BMP, HDR

 

附带处理耗时计算,示例演示了一个简单的反色处理算法,并简单注释了一下部分逻辑。

 

完整代码:

#include 
#include
#include
#include
#include
#include
//使用stbImage http://nothings.org/#define STB_IMAGE_IMPLEMENTATION#include "stb_image.h"#define STB_IMAGE_WRITE_IMPLEMENTATION#include "stb_image_write.h" //如果是Windows的话,调用系统API ShellExecuteA打开图片#if defined(_MSC_VER)#include
#define USE_SHELL_OPEN#endif//是否使用OMP方式计时#define USE_OMP 0#if USE_OMP#include
auto const epoch = omp_get_wtime();double now() { return omp_get_wtime() - epoch; };#else#include
auto const epoch = std::chrono::steady_clock::now();double now() { return std::chrono::duration_cast
(std::chrono::steady_clock::now() - epoch).count() / 1000.0;};#endif//计时函数template
double bench(const FN &fn) { auto took = -now(); return (fn(), took + now());}//存储当前传入文件位置的变量std::string m_curFilePath;//加载图片void loadImage(const char* filename, unsigned char*& Output, int &Width, int &Height, int &Channels){ Output = stbi_load(filename, &Width, &Height, &Channels, 0);}//保存图片void saveImage(const char* filename, int Width, int Height, int Channels, unsigned char* Output, bool open = true){ std::string saveFile = m_curFilePath; saveFile += filename; //保存为png,也可以调用stbi_write_bmp 保存为bmp stbi_write_png(saveFile.c_str(), Width, Height, Channels, Output, 0);#ifdef USE_SHELL_OPEN if (open) ShellExecuteA(NULL, "open", saveFile.c_str(), NULL, NULL, SW_SHOW);#else //其他平台暂不实现#endif}//取当前传入的文件位置void getCurrentFilePath(const char* filePath, std::string& curFilePath){ char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; curFilePath.clear(); _splitpath_s(filePath, drive, dir, fname, ext); curFilePath += drive; curFilePath += dir; curFilePath += fname; curFilePath += "_";}//算法处理,这里以一个反色作为例子void processImage(unsigned char* Input, unsigned char* Output, unsigned int Width, unsigned int Height, unsigned int Channels){ int WidthStep = Width*Channels; if (Channels == 1) { for (unsigned int Y = 0; Y < Height; Y++) { unsigned char* pOutput = Output + (Y * WidthStep); unsigned char* pInput = Input + (Y * WidthStep); for (unsigned int X = 0; X < Width; X++) { pOutput[0] = 255 - pInput[0]; //下一个像素点 pInput += Channels; pOutput += Channels; } } } else if (Channels == 3 || Channels == 4) { for (unsigned int Y = 0; Y < Height; Y++) { unsigned char* pOutput = Output + (Y * WidthStep); unsigned char* pInput = Input + (Y * WidthStep); for (unsigned int X = 0; X < Width; X++) { pOutput[0] = 255 - pInput[0]; pOutput[1] = 255 - pInput[1]; pOutput[2] = 255 - pInput[2]; //通道数为4时,不处理A通道反色(pOutput[3] = 255 - pInput[3];) //下一个像素点 pInput += Channels; pOutput += Channels; } } }}//本人博客:http://tntmonks.cnblogs.com/转载请注明出处.int main(int argc, char **argv) { std::cout << "Image Processing " << std::endl; std::cout << "Demo By Gaozhihan (Build 2016-03-22)" << std::endl; std::cout << "支持解析如下图片格式:" << std::endl; std::cout << "JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC" << std::endl; //检查参数是否正确 if (argc < 2) { std::cout << "参数错误。" << std::endl; std::cout << "请拖放文件到可执行文件上,或使用命令行:imageProc.exe 图片" << std::endl; std::cout << "例如: imageProc.exe d:image.jpg" << std::endl; return 0; } std::string szfile = argv[1]; //检查输入的文件是否存在 if (_access(szfile.c_str(), 0) == -1) { std::cout << "输入的文件不存在,参数错误!" << std::endl; } getCurrentFilePath(szfile.c_str(), m_curFilePath); int Width = 0; //图片宽度 int Height = 0; //图片高度 int Channels = 0; //图片通道数 unsigned char* inputImage = NULL; //输入图片指针 double nLoadTime = bench([&]{ //加载图片 loadImage(szfile.c_str(), inputImage, Width, Height, Channels); }); std::cout << " 加载耗时: " << int(nLoadTime * 1000) << " 毫秒" << std::endl; if ((Channels != 0) && (Width != 0) && (Height != 0)) { //分配与载入同等内存用于处理后输出结果 unsigned char* outputImg = (unsigned char*)STBI_MALLOC(Width*Channels*Height*sizeof(unsigned char)); if (inputImage) { //如果图片加载成功,则将内容复制给输出内存,方便处理 memcpy(outputImg, inputImage, Width*Channels*Height); } else { std::cout << " 加载文件: " << szfile.c_str() << " 失败!" << std::endl; } double nProcessTime = bench([&]{ //处理算法 processImage(inputImage, outputImg, Width, Height, Channels); }); std::cout << " 处理耗时: " << int(nProcessTime * 1000) << " 毫秒" << std::endl; //保存处理后的图片 double nSaveTime = bench([&]{ saveImage("_done.png", Width, Height, Channels, outputImg); }); std::cout << " 保存耗时: " << int(nSaveTime * 1000) << " 毫秒" << std::endl; //释放占用的内存 if (outputImg) { STBI_FREE(outputImg); outputImg = NULL; } if (inputImage) { STBI_FREE(inputImage); inputImage = NULL; } } else { std::cout << " 加载文件: " << szfile.c_str() << " 失败!" << std::endl; } getchar(); std::cout << "按任意键退出程序 " << std::endl; return 0;}

  

示例具体流程为:

加载图片->算法处理->保存图片->打开保存图片(仅Windows)

并对 加载,处理,保存 这三个环节都进行了耗时计算并输出。

 

:

http://files.cnblogs.com/files/tntmonks/imageProcDemo.zip

转载于:https://www.cnblogs.com/huty/p/8517120.html

你可能感兴趣的文章
Hallo wolrd!
查看>>
16下学期进度条2
查看>>
前端页面卡顿-代码优化
查看>>
nagios通过脚本对系统进行定制监控
查看>>
jquery判断点击鼠标左、中、右键事件
查看>>
java线程池原理
查看>>
为什么子类的构造方法在运行之前,必须调用父类的构造方法?能不能反过来?为什么不能反过来?...
查看>>
Could not resolve view with name '***' in servlet with name 'dispatcher'
查看>>
springBoot配置elasticsearch搜索
查看>>
Chapter 3 Phenomenon——12
查看>>
MyBatis源码解析【6】SqlSession运行
查看>>
中小学教育缴费遇到的一些问题
查看>>
FAIR开源Detectron:整合全部顶尖目标检测算法
查看>>
C语言中求最大最小值的库函数
查看>>
SRS
查看>>
14.typescript-类与接口
查看>>
js学习(精华帖)
查看>>
和小哥哥一起刷洛谷(1)
查看>>
分享squid缓存服务器配置-之conf配置文件的详细介绍
查看>>
jQuery教程详解(一)
查看>>