分享 C++图像处理的代码简易示例
采用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 <windows.h> #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 <math.h> #include <io.h> #include <iostream> #include <string> #include <chrono> //计时 auto const epoch = std::chrono::steady_clock::now(); static double now() { return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - epoch).count() / 1000.0; }; template <typename FN> 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, ); } //保存图片 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; ) { ; Y < Height; Y++) { unsigned char *scanLineOut = Output + (Y * Stride); unsigned char *scanLineIn = Input + (Y * Stride); ; X < Width; X++) { scanLineOut[] = - scanLineIn[]; scanLineIn++; scanLineOut++; } } } || Channels == ) { ; Y < Height; Y++) { unsigned char *scanLineOut = Output + (Y * Stride); unsigned char *scanLineIn = Input + (Y * Stride); ; X < Width; X++) { scanLineOut[] = - scanLineIn[]; scanLineOut[] = - scanLineIn[]; scanLineOut[] = - scanLineIn[]; //通道数为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; //检查参数是否正确 ) { std::cout << "参数错误。" << std::endl; std::cout << "请拖放文件到可执行文件上,或使用命令行:imageProc.exe 图片" << std::endl; std::cout << "例如: imageProc.exe d:\\image.jpg" << std::endl; ; } std::]; //检查输入的文件是否存在 ) == -) { std::cout << "输入的文件不存在,参数错误!" << std::endl; } getCurrentFilePath(szfile.c_str(), m_curFilePath); ; //图片宽度 ; //图片高度 ; //图片通道数 unsigned char *inputImage = NULL; //输入图片指针 double nLoadTime = bench([&] { //加载图片 loadImage(szfile.c_str(), inputImage, Width, Height, Channels); }); std::cout << ) << " 毫秒" << std::endl; ) && (Width != ) && (Height != )) { //分配与载入同等内存用于处理后输出结果 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 << ) << " 毫秒" << std::endl; //保存处理后的图片 double nSaveTime = bench([&] { saveImage("_done.jpg", Width, Height, Channels, outputImg); }); std::cout << ) << " 毫秒" << 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)
并对 加载,处理,保存 这三个环节都进行了耗时计算并输出。
参考资源:http://www.cnblogs.com/tntmonks/p/5305844.html
后续博主将基于该模板,分享基于cpu的图像算法系列文章。
分享 C++图像处理的代码简易示例的更多相关文章
- demo工程的清单文件及activity中api代码简单示例
第一步注册一个账户,并创建一个应用.获取app ID与 app Key. 第二步下载sdk 第三步新建工程,修改清单文件,导入相关的sdk文件及调用相应的api搞定. 3.1 修改清单文件,主要是加入 ...
- iOS开发数据库篇—SQL代码应用示例
iOS开发数据库篇—SQL代码应用示例 一.使用代码的方式批量添加(导入)数据到数据库中 1.执行SQL语句在数据库中添加一条信息 插入一条数据的sql语句: 点击run执行语句之后,刷新数据 2.在 ...
- ROBOTS.TXT屏蔽笔记、代码、示例大全
自己网站的ROBOTS.TXT屏蔽的记录,以及一些代码和示例: 屏蔽后台目录,为了安全,做双层管理后台目录/a/xxxx/,蜘蛛屏蔽/a/,既不透露后台路径,也屏蔽蜘蛛爬后台目录 缓存,阻止蜘蛛爬静态 ...
- 老李分享:pep8 python代码规范
老李分享:pep8 python代码规范 什么是PEPPEP是 Python Enhancement Proposal 的缩写,翻译过来就是 Python增强建议书 . PEP8 译者:本文基于 20 ...
- android 代码混淆示例
参考其它资料为项目代码做了一下混淆 项目中使用了 slidingmenu actionbarsherlock fastjson volley httpclient 等第三方库, 并使用了 ...
- 一个微服务+DDD(领域驱动设计)的代码结构示例
前有幸拜读过诸多大神关于DDD的实现落地等文章,学习较多,受益匪浅,在此推荐 : https://www.cnblogs.com/hafiz/p/9388334.htmlhttps://blog.cs ...
- 深度学习之卷积神经网络CNN及tensorflow代码实现示例
深度学习之卷积神经网络CNN及tensorflow代码实现示例 2017年05月01日 13:28:21 cxmscb 阅读数 151413更多 分类专栏: 机器学习 深度学习 机器学习 版权声明 ...
- 分享用于学习C++图像处理的代码示例
为了便于学习图像处理并研究图像算法, 俺写了一个适合初学者学习的小小框架. 麻雀虽小五脏俱全. 采用的加解码库:stb_image 官方:http://nothings.org/ stb_image. ...
- js 分享代码--完整示例代码
<div class="bdsharebuttonbox" data-tag="share_1"> <a class="bds_ms ...
随机推荐
- 【源码分享】mui实现简单的手机音乐播放器
mui实现简单的手机音乐播放器 最近先来无事,我用mui写了一个可以跨页面控制的音乐播放器.主要功能有上一曲,下一曲,播放,暂停,感兴趣的可以继续看下去. 说的总是不实在,直接上源码,有兴趣的可以读下 ...
- ICG_System之全自动代码生成器V2.0版本
大家好! 早在2014年本人就已经利用业余时间开发自己的ICG之代码生成器系统.依靠bootstrap的崛起本人也在不断完善此应用.目的是为了减少开发人员的工作量. 减少不必要的复制粘贴操作,该系统已 ...
- Jquery DataTables 使用AJAX POST的问题
最近项目在用需要用表格,听说DataTables很好很强大,于是用了一下. Get请求没什么问题,问题处在POST请求上 Jquery原生的POST请求没有问题,代码如下 $.ajax({ url ...
- 多行文本省略号的实现.html
多行文本省略号的实现 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...
- PHP加密解密数字
<?php /** * 加密解密类,PHP加密解密数字,适用于URL加密 * 该算法仅支持加密数字.比较适用于数据库中id字段的加密解密,以及根据数字显示url的加密. * @version a ...
- [故障公告]14:40-15:00博客站点web服务器雪崩似的CPU 100%
非常抱歉,今天下午14:40-15:00左右,web服务器突然雪崩似的出现CPU 100%问题,造成博客站点无法访问(503).由此给您带来很大的麻烦,请您谅解. 在问题出现之前,博客站点运行着5台w ...
- [图形学] 结束 [Unity Shader] 开始
历时4个月,终于把<计算机图形学 with OpenGL>啃完了.如果边上班边看,即使一年应该都看不完. 虽然书里用到的GLUT库应该已经废弃,但并不影响用它去理解图形学的内容,我只把它当 ...
- spring +springmvc+mybatis组合applicationContext.xml文件配置
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...
- raft如何实现Linearizable Read
Linearizable Read通俗来讲,就是读请求需要读到最新的已经commit的数据,不会读到老数据. 对于使用raft协议来保证多副本强一致的系统中,读写请求都可以通过走一次raft协议来满足 ...
- css中的层叠性及权重的比较
假如同一个标签被多个选择器选中,每个选择器都设置了相同的样式,浏览器中加载时这个样式听谁的? 不同选择器设置的同一个样式,只会选择一个进行加载,不会叠加. 为了解决听谁的问题,引入层叠性的概念. 层叠 ...