博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
分享用于学习C++图像处理的代码示例
阅读量:7282 次
发布时间:2019-06-30

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

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

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

 

麻雀虽小五脏俱全。

采用Decoder:stb_image

https://github.com/nothings/stb/blob/master/stb_image.h

采用Encoder:tiny_jpeg

https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h

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

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

tiny_jpeg.h用于保存JPG格式。

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

完整代码:

//如果是Windows的话,调用系统API ShellExecuteA打开图片#if defined(_MSC_VER)#define _CRT_SECURE_NO_WARNINGS#include 
#define USE_SHELL_OPEN#endif#define STB_IMAGE_STATIC#define STB_IMAGE_IMPLEMENTATION#include "stb_image.h"//ref:https://github.com/nothings/stb/blob/master/stb_image.h#define TJE_IMPLEMENTATION#include "tiny_jpeg.h" //ref:https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h#include
#include
#include
#include
#include
//计时 auto const epoch = std::chrono::steady_clock::now();static double now(){ return std::chrono::duration_cast
(std::chrono::steady_clock::now() - epoch).count() / 1000.0;};template
static 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; //保存为jpg if (!tje_encode_to_file(saveFile.c_str(), Width, Height, Channels, Output)) { fprintf(stderr, "写入 JPEG 文件失败.\n"); return; }#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 Stride = Width * Channels; if (Channels == 1) { for (unsigned int Y = 0; Y < Height; Y++) { unsigned char *scanLineOut = Output + (Y * Stride); unsigned char *scanLineIn = Input + (Y * Stride); for (unsigned int X = 0; X < Width; X++) { scanLineOut[0] = 255 - scanLineIn[0]; scanLineIn++; scanLineOut++; } } } else if (Channels == 3 || Channels == 4) { for (unsigned int Y = 0; Y < Height; Y++) { unsigned char *scanLineOut = Output + (Y * Stride); unsigned char *scanLineIn = Input + (Y * Stride); for (unsigned int X = 0; X < Width; X++) { scanLineOut[0] = 255 - scanLineIn[0]; scanLineOut[1] = 255 - scanLineIn[1]; scanLineOut[2] = 255 - scanLineIn[2]; //通道数为4时,不处理A通道反色(scanLineOut[3] = 255- scanLineIn[3]; scanLineIn += Channels; scanLineOut += Channels; } } }}int main(int argc, char **argv){ std::cout << "Image Processing " << std::endl; std::cout << "博客:http://cpuimage.cnblogs.com/" << 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 << " 加载文件: \n" << 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.jpg", Width, Height, Channels, outputImg); }); std::cout << " 保存耗时: " << int(nSaveTime * 1000) << " 毫秒" << std::endl; //释放占用的内存 if (outputImg) { stbi_image_free(outputImg); outputImg = NULL; } if (inputImage) { stbi_image_free(inputImage); inputImage = NULL; } } else { std::cout << " 加载文件: \n" << szfile.c_str() << " 失败!" << std::endl; } getchar(); std::cout << "按任意键退出程序 \n" << std::endl; return EXIT_SUCCESS;}

 

示例具体流程为:

加载图片(拖放文件到可执行文件上)->算法处理->保存图片->打开保存图片(仅Windows)

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

  

若有其他相关问题或者需求也可以邮件联系俺探讨。

邮箱地址是: 

gaozhihan@vip.qq.com

 

若此博文能帮到您,欢迎扫码小额赞助。

微信:  

 

 

支付宝: 

转载于:https://www.cnblogs.com/cpuimage/p/5305844.html

你可能感兴趣的文章
最简单的读文本文件
查看>>
Ubuntu下搭建sun-jdk和Maven2
查看>>
zabbix数据库备份
查看>>
Virtual PC 2007下虚拟机与本机双XP系统实现互联与上网详解
查看>>
css中display设置为table、table-row、table-cell后的作用及其注意点
查看>>
Linux学习笔记
查看>>
帝国CMS网站管理系统安装方法图文教程
查看>>
Domino 8.5 迁移步骤-看图说话
查看>>
Openssl及加密解密(二)openssl
查看>>
个性心理测试
查看>>
Redis集群及管理讲解
查看>>
ps命令详解
查看>>
配置系列:ssm中applicationContext.xml的简单配置
查看>>
nginx启动脚本
查看>>
linux 出现bash: ****: /lib64/ld-linux-x86-64.so.2: bad ELF interpreter: No such file or directory
查看>>
kickstart安装linux
查看>>
蓝色心情win7主题一键安装包 v 2.0
查看>>
MySQL5.7修改密码
查看>>
10个趣味Linux动画命令
查看>>
Linux协议栈(4)——sk_buff及代码
查看>>