采用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++图像处理的代码简易示例的更多相关文章

  1. demo工程的清单文件及activity中api代码简单示例

    第一步注册一个账户,并创建一个应用.获取app ID与 app Key. 第二步下载sdk 第三步新建工程,修改清单文件,导入相关的sdk文件及调用相应的api搞定. 3.1 修改清单文件,主要是加入 ...

  2. iOS开发数据库篇—SQL代码应用示例

    iOS开发数据库篇—SQL代码应用示例 一.使用代码的方式批量添加(导入)数据到数据库中 1.执行SQL语句在数据库中添加一条信息 插入一条数据的sql语句: 点击run执行语句之后,刷新数据 2.在 ...

  3. ROBOTS.TXT屏蔽笔记、代码、示例大全

    自己网站的ROBOTS.TXT屏蔽的记录,以及一些代码和示例: 屏蔽后台目录,为了安全,做双层管理后台目录/a/xxxx/,蜘蛛屏蔽/a/,既不透露后台路径,也屏蔽蜘蛛爬后台目录 缓存,阻止蜘蛛爬静态 ...

  4. 老李分享:pep8 python代码规范

    老李分享:pep8 python代码规范 什么是PEPPEP是 Python Enhancement Proposal 的缩写,翻译过来就是 Python增强建议书 . PEP8 译者:本文基于 20 ...

  5. android 代码混淆示例

    参考其它资料为项目代码做了一下混淆 项目中使用了 slidingmenu   actionbarsherlock   fastjson  volley   httpclient 等第三方库, 并使用了 ...

  6. 一个微服务+DDD(领域驱动设计)的代码结构示例

    前有幸拜读过诸多大神关于DDD的实现落地等文章,学习较多,受益匪浅,在此推荐 : https://www.cnblogs.com/hafiz/p/9388334.htmlhttps://blog.cs ...

  7. 深度学习之卷积神经网络CNN及tensorflow代码实现示例

    深度学习之卷积神经网络CNN及tensorflow代码实现示例 2017年05月01日 13:28:21 cxmscb 阅读数 151413更多 分类专栏: 机器学习 深度学习 机器学习   版权声明 ...

  8. 分享用于学习C++图像处理的代码示例

    为了便于学习图像处理并研究图像算法, 俺写了一个适合初学者学习的小小框架. 麻雀虽小五脏俱全. 采用的加解码库:stb_image 官方:http://nothings.org/ stb_image. ...

  9. js 分享代码--完整示例代码

    <div class="bdsharebuttonbox" data-tag="share_1"> <a class="bds_ms ...

随机推荐

  1. 门(door)

    门(door) 时间限制: 1 Sec  内存限制: 128 MB 题目描述 输入 第一行是一个正整数n,表示原始字符串的长度.第二行是一个字符串,长度为n.字符串由大小写字母,数字,符号,空格构成. ...

  2. h5之scrollIntoView控制页面元素滚动

    如果滚动页面也是DOM没有解决的一个问题.为了解决这个问题,浏览器实现了一下方法,以方便开发人员如何更好的控制页面的滚动.在各种专有方法中,HTML5选择了scrollIntoView()作为标准方法 ...

  3. maven打包 bat自动化打包

    maven打包,首先cd到项目根目录,如果想跳过测试阶段,可用:mvn package -DskipTests bat命令,说明start是打开文件夹的意思:e: cd E:\workspace\it ...

  4. 《JavaScript高级程序设计》笔记二

    第二章 在HTML中使用JavaScript 要想把JavaScript放到网页中,就必须涉及到Web的核心语言HTML.向HTML页面中插入JavaScript的主要方法,就是使用<scrip ...

  5. php中的date函数

    一.带零 echo date('Y-m-d');2012-08-08二.不带零 echo date('Y-n-j');2012-8-8

  6. java基础系列--Date类

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/7126930.html 1.Date类概述 Date类是从JDK1.1就开始存在的老类,其提 ...

  7. C#深入学习 ----多线程学习(一)第一天学习

    学习最好的方法就是总结,并写下来,能让别人看懂,自己肯定是掌握了的. 针对软件开发,一直停留在能做的层次,今天得到大牛指点,觉得有必要对这门技术深入学习. 翻阅园内各大神的文章,收益匪浅,在这里做下总 ...

  8. nth-child 和nth-type的区别

    一.深呼吸,直接内容:nth-child和:nth-of-type都是CSS3中的伪类选择器,其作用近似却又不完全一样,对于不熟悉的人对其可能不是很区分,本文就将介绍两者的不同,以便于大家正确灵活使用 ...

  9. React--JSX语法

    JSX语法,它是js语言的语法拓展. 比如2+2 , 对象.属性 , 函数的调用都可以在jsx中书写. import React from "react"; export defa ...

  10. 在linux环境下tomcat 指定 jdk或jre版本

    最近在服务器上部署的服务出了点问题,后来查到是因为JDK版本太高了,程序识别不了,需要把JDK降级. 但是服务器上面跑的程序很多,又不能直接把环境变量改了,所以只能想着怎么把这个出问题的工程服务指定j ...