分享 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 ...
随机推荐
- 使用awk进行日志信息的分组统计
起因 这是今天我线上出了一个bug,需要查看日志并统计一个我需要的信息出现的频率,可以叫做分组统计. 日志文件部分内容 00:09:07.655 [showcase_backend][topsdk] ...
- Git操作简介
一 概述 1.什么是Git? Git是分布式版本控制系统. 2.集中式与分布式对比 在集中式版本控制系统中,版本库集中在中央服务器上,每次工作时都需要先从中央服务器获取最新版本,修改后,再推送到中央服 ...
- 【从零开始】用node搭建一个jsonp&json服务
目录: 一.介绍 二.node安装 三.webstorm配置node环境 四.代码介绍 五.如何使用 六.自定义域名 七.其他 一.介绍 1.背景 日常工作中,跟后端商定好接口格式后:通常采用 ...
- 【Android Developers Training】 83. 实现高效网络访问来优化下载
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- easyui(一) 初始easyui
中午贪睡,睡到3点多,爬起来赶紧学习,学习是我快乐(自我催眠).哈哈~ --WH 一.什么是easyui? 学习一个东西,最重要的是知道它的定位(是干嘛的,基本的用法是什么,快速入门),其实easyu ...
- eclipse更改maven的本地路径和外部仓库地址
背景 当前使用eclipse自带的maven碰到两个蛋疼的问题: maven在国内使用如果不进行FQ则会痛苦不堪如便秘. maven下载大量jar包导致某盘不够用,需要换大的分区. 因此为了解决这个问 ...
- Struts2之初识篇(一)——与struts的区别和基本配置
Struts2资源下载地址: Struts官方地址:http://struts.apache.org/ 我这里下载了struts2的最新版本struts2-2.5.10.1-all.所有内容如下图: ...
- Chrome控制台使用详解
Chrome的开发者工具已经强大到没朋友的地步了,特别是其功能丰富界面友好的console,使用得当可以有如下功效: 更高「逼格」更快「开发调试」更强「进阶级的Frontender」 Bug无处遁形「 ...
- kotlin的一些特性介绍和与java C#的简单对比
前言 这是我之前在知乎上的一些回答的汇总,感觉还是博客园写这些东西方便一点,也算是理下我的一些思路,现将文章整理后,发布在园子里. 为何是kotlin: 很多人对kt没有一个正确的定位,可能大家第一反 ...
- PHP源码阅读strtr
strtr 转换字符串中特定的字符,但是这个函数使用的方式多种. echo strtr('hello world', 'hw', 'ab'); // 第一种 aello borld echo strt ...