windows C++-创建图像处理的异步消息(二)

 创建图像处理网络

此部分介绍如何创建对给定目录中的每个 JPEG (.jpg) 图像执行图像处理的异步消息块网络。 网络执行以下图像处理操作:

  1. 对于 Tom 创作的任何图像,转换为灰度。

  2. 对于任何以红色作为主色的图像,移除绿色和蓝色分量,然后将其变暗。

  3. 对于任何其他图像,应用棕色调。

网络仅应用与其中一个条件匹配的第一个图像处理操作。 例如,如果图像由 Tom 创作,并且将红色作为其主色,则图像仅转换为灰度。

网络执行每个图像处理操作后,它会将图像作为位图 (.bmp) 文件保存到磁盘。

以下步骤演示如何创建实现此图像处理网络的函数,并将该网络应用于给定目录中的每个 JPEG 图像。

创建图像处理网络

// 1. 创建函数 ProcessImages,它会采用磁盘上某个目录的名称。void ProcessImages(const wstring& directory)
{
}// 2. 在 ProcessImages 函数中,创建 countdown_event 变量。 本演练稍后会对 countdown_event 类进行介绍。
// Holds the number of active image processing operations and 
// signals to the main thread that processing is complete.
countdown_event active(0);// 3. 创建将 Bitmap 对象与其原始文件名关联的 std::map 对象。
// Maps Bitmap objects to their original file names.
map<Bitmap*, wstring> bitmap_file_names;// 4. 添加以下代码以定义图像处理网络的成员。//// Create the nodes of the network.//// Loads Bitmap objects from disk.transformer<wstring, Bitmap*> load_bitmap([&](wstring file_name) -> Bitmap* {Bitmap* bmp = new Bitmap(file_name.c_str());if (bmp != nullptr)bitmap_file_names.insert(make_pair(bmp, file_name));return bmp;});// Holds loaded Bitmap objects.unbounded_buffer<Bitmap*> loaded_bitmaps;// Converts images that are authored by Tom to grayscale.transformer<Bitmap*, Bitmap*> grayscale([](Bitmap* bmp) {return Grayscale(bmp);},nullptr,[](Bitmap* bmp) -> bool {if (bmp == nullptr)return false;// Retrieve the artist name from metadata.UINT size = bmp->GetPropertyItemSize(PropertyTagArtist);if (size == 0)// Image does not have the Artist property.return false;PropertyItem* artistProperty = (PropertyItem*) malloc(size);bmp->GetPropertyItem(PropertyTagArtist, size, artistProperty);string artist(reinterpret_cast<char*>(artistProperty->value));free(artistProperty);return (artist.find("Tom ") == 0);});// Removes the green and blue color components from images that have red as// their dominant color.transformer<Bitmap*, Bitmap*> colormask([](Bitmap* bmp) {return ColorMask(bmp, 0x00ff0000);},nullptr,[](Bitmap* bmp) -> bool { if (bmp == nullptr)return false;return (GetColorDominance(bmp) == 0x00ff0000);});// Darkens the color of the provided Bitmap object.transformer<Bitmap*, Bitmap*> darken([](Bitmap* bmp) {return Darken(bmp, 50);});// Applies sepia toning to the remaining images.transformer<Bitmap*, Bitmap*> sepiatone([](Bitmap* bmp) {return Sepiatone(bmp);},nullptr,[](Bitmap* bmp) -> bool { return bmp != nullptr; });// Saves Bitmap objects to disk.transformer<Bitmap*, Bitmap*> save_bitmap([&](Bitmap* bmp) -> Bitmap* {// Replace the file extension with .bmp.wstring file_name = bitmap_file_names[bmp];file_name.replace(file_name.rfind(L'.') + 1, 3, L"bmp");// Save the processed image.CLSID bmpClsid;GetEncoderClsid(L"image/bmp", &bmpClsid);      bmp->Save(file_name.c_str(), &bmpClsid);return bmp;});// Deletes Bitmap objects.transformer<Bitmap*, Bitmap*> delete_bitmap([](Bitmap* bmp) -> Bitmap* {      delete bmp;return nullptr;});// Decrements the event counter.call<Bitmap*> decrement([&](Bitmap* _) {      active.signal();});// 5. 添加以下代码以连接网络。
//
// Connect the network.
//   load_bitmap.link_target(&loaded_bitmaps);loaded_bitmaps.link_target(&grayscale);
loaded_bitmaps.link_target(&colormask);   
colormask.link_target(&darken);
loaded_bitmaps.link_target(&sepiatone);
loaded_bitmaps.link_target(&decrement);grayscale.link_target(&save_bitmap);
darken.link_target(&save_bitmap);
sepiatone.link_target(&save_bitmap);save_bitmap.link_target(&delete_bitmap);
delete_bitmap.link_target(&decrement);// 6. 添加以下代码以向网络头发送目录中每个 JPEG 文件的完整路径。// Traverse all files in the directory.
wstring searchPattern = directory;
searchPattern.append(L"\\*");WIN32_FIND_DATA fileFindData;
HANDLE hFind = FindFirstFile(searchPattern.c_str(), &fileFindData);
if (hFind == INVALID_HANDLE_VALUE) return;
do
{if (!(fileFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)){wstring file = fileFindData.cFileName;// Process only JPEG files.if (file.rfind(L".jpg") == file.length() - 4){// Form the full path to the file.wstring full_path(directory);full_path.append(L"\\");full_path.append(file);// Increment the count of work items.active.add_count();// Send the path name to the network.send(load_bitmap, full_path);}}
}
while (FindNextFile(hFind, &fileFindData) != 0); 
FindClose(hFind);// 7. 等待 countdown_event 变量达到零。
// Wait for all operations to finish.
active.wait();

图像网络成员

下表描述了网络的成员:

a06aca143e494df2bb35be9e5942b61b.png

loaded_bitmaps 消息缓冲区非常重要,因为作为 unbounded_buffer 对象,它可向多个接收方提供 Bitmap 对象。 当目标块接受 Bitmap 对象时,unbounded_buffer 对象不会向任何其他目标提供该 Bitmap 对象。 因此,将对象链接到 unbounded_buffer 对象的顺序非常重要。 grayscale、colormask 和 sepiatone 消息块各自都使用筛选器,以便仅接受特定 Bitmap 对象。 decrement 消息缓冲区是 loaded_bitmaps 消息缓冲区的重要目标,因为它接受其他消息缓冲区所拒绝的所有 Bitmap 对象。 需要 unbounded_buffer 对象以便按顺序传播消息。 因此,unbounded_buffer 对象会在新目标块链接到它之前阻塞,并在没有当前目标块接受该消息时接受消息。

如果应用程序需要多个消息块处理消息,而不只是第一个接受消息的消息块,则可以使用另一种消息块类型,例如 overwrite_buffer。 overwrite_buffer 类一次保存一个消息,但它会将该消息传播到其每个目标。

下表描述了网络的成员。

5ec818868ef048919c5af660a3d9c464.png

此示例中的 countdown_event 对象使图像处理网络能够在处理了所有图像后告知主应用程序。 countdown_event 类使用 concurrency::event 对象在计数器值达到零时发送信号。 主应用程序在每次将文件名发送到网络时使计数器递增。 网络终端节点在处理每个图像后使计数器递减。 在主应用程序遍历指定目录后,它会等待 countdown_event 对象发出指示其计数器已达到零的信号。

下面的示例展示了 countdown_event 类:

// A synchronization primitive that is signaled when its 
// count reaches zero.
class countdown_event
{
public:countdown_event(unsigned int count = 0): _current(static_cast<long>(count)) {// Set the event if the initial count is zero.if (_current == 0L)_event.set();}// Decrements the event counter.void signal() {if(InterlockedDecrement(&_current) == 0L) {_event.set();}}// Increments the event counter.void add_count() {if(InterlockedIncrement(&_current) == 1L) {_event.reset();}}// Blocks the current context until the event is set.void wait() {_event.wait();}private:// The current count.volatile long _current;// The event that is set when the counter reaches zero.event _event;// Disable copy constructor.countdown_event(const countdown_event&);// Disable assignment.countdown_event const & operator=(countdown_event const&);
};

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1557846.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

如何避免PuTTY的连接超时

问题&#xff1a;使用PuTTY默认创建的SSH连接&#xff0c;过一会就会提示“Remote side unexpectedly closed network connection" 解决方法&#xff1a; 要防止PuTTY会话由于空闲而断开连接&#xff0c;可以通过启用keep-alives功能&#xff0c;使PuTTY定期向远程主机发…

2-116 基于matlab的主成分分析(PCA)及累积总和(CUSUM)算法故障监测

基于matlab的主成分分析&#xff08;PCA&#xff09;及累积总和&#xff08;CUSUM&#xff09;算法故障监测&#xff0c;针对传统的多元统计分析方法对生产过程中微小故障检测不灵敏的问题&#xff0c;使用基于主元分析的累积和的微小故障检测方法进行故障监测&#xff0c;通过…

【多重循环在Java中的应用】

多重循环在Java中的应用 介绍 多重循环是将一个循环嵌套在另一个循环体内的编程结构。Java中的 for、while 和 do...while 循环均可作为外层循环和内层循环。建议使用两层嵌套&#xff0c;最多不超过三层&#xff0c;以保持代码的可读性。 在多重循环中&#xff0c;外层循环执…

开源项目都是怎么推广的?

大家好&#xff0c;我是爱折腾的刘大逵。跟我接触过的技术们都知道&#xff0c;一年一年的都在折腾着做一些项目&#xff0c;年年有进步&#xff0c;年年有想法&#xff0c;年年在折腾。今天给大家分享GITEE如何上推荐&#xff01; GITEE推荐有什么用&#xff1f; 众所周知&a…

DDD简介

概述 传统的数据驱动开发模式&#xff0c;View、Service、Dao这种三层分层模式&#xff0c;会很自然的写出过程式代码&#xff0c;这种开发方式中的对象只是数据载体&#xff0c;而没有行为&#xff0c;是一种贫血对象模型。以数据为中心&#xff0c;以数据库ER图为设计驱动&a…

回到原点再出发

原文What Goes Around Comes Around作者Michael Stonebraker & Joseph M. Hellerstein其他译文https://zhuanlan.zhihu.com/p/111322429 1. 摘要 本文总结了近35年来的数据模型方案&#xff0c;分成9个不同的时代&#xff0c;讨论了每个时代的方案。我们指出&#xff0c;…

Linux安装配置Jupyter Lab并开机自启

文章目录 1、安装配置jupyter lab首先需要使用pip3安装&#xff1a;生成配置文件和密码&#xff1a; 2、设置开机自启首先通过which jupyter查询到可执行文件路径&#xff1a;设置自启服务&#xff1a; 1、安装配置jupyter lab 首先需要使用pip3安装&#xff1a; pip3 instal…

(22)以RS码为例说明信道编码AWGN信道的Eb/N0设置

文章目录 前言一、编码Eb/N0与未编码Eb/N0及编码码率二、仿真代码三、仿真结果 前言 本文说明了如何为采用信道编码的通信链路设置Eb/N0&#xff08;比特能量与噪声功率谱密度比&#xff09;。 一、编码Eb/N0与未编码Eb/N0及编码码率 在通信系统仿真中&#xff0c;如果采用了…

10.8摩尔学习知识点

今天学习获取数据 在摩尔云平台找到要修改的主视图&#xff0c;然后点击操作功能&#xff0c;点击新增&#xff0c;直接输入名字获取数据&#xff0c;然后&#xff0c;显示顺序15&#xff0c;显示是&#xff0c;点击确定&#xff0c;然后就是自定义类上面输入创建的类名&#…

怎么在抖音直播间录屏?主播会知道吗?录屏软件推荐

在抖音直播间录屏&#xff0c;主播通常不会收到直接通知提示某个观众正在录屏。在抖音直播间录屏&#xff0c;主播通常是不知道的。抖音平台没有为主播提供查看观众录屏行为的相关功能或提示&#xff0c;所以从平台功能角度来说&#xff0c;主播无法直接察觉观众的录屏操作。 然…

『网络游戏』窗口基类【06】

创建脚本&#xff1a;WindowRoot.cs 编写脚本&#xff1a; 修改脚本&#xff1a;LoginWnd.cs 修改脚本&#xff1a;LoadingWnd.cs 修改脚本&#xff1a;ResSvc.cs 修改脚本&#xff1a;LoginSys.cs 运行项目 - 功能不变 本章结束

职场中的人情世故,你懂了多少?

职场如战场&#xff0c;稍有不慎&#xff0c;满盘皆输。 职场如江湖&#xff0c;不是打打杀杀&#xff0c;而是人情世故。 成年人的世界里没有“容易”二字&#xff0c;我们也需要懂得哪些人情世故和。 职场上的各种光怪陆离现象&#xff0c;有很多职场人吐槽&#xff1a;“…

以后再也不要说程序员不能拿诺贝尔了

当地时间10月8日&#xff0c;瑞典皇家科学院宣布&#xff0c;将2024年诺贝尔物理学奖授予美国普林斯顿大学的约翰霍普菲尔德&#xff08;John J. Hopfield&#xff09;和加拿大多伦多大学的杰弗里辛顿&#xff08;Geoffrey E. Hinton&#xff09;&#xff0c;以表彰他们“为推动…

基于SSM车位租赁系统【附源码】

基于SSM车位租赁系统 效果如下&#xff1a; 注册页面 首页展示 车位租赁订单展示 车位列表页面 公告信息管理页面 公告类型管理界面 研究背景 随着经济的持续增长和城市化进程的加速&#xff0c;土地资源变得日益紧缺&#xff0c;停车难问题已成为许多城市面临的共同挑战。随…

力扣LeetCode-链表中的循环与递归使用

标题做题的时候发现循环与递归的使用差别&#xff1a; 看两道题&#xff1a; 两道题都是不知道链表有多长&#xff0c;所以需要用到循环&#xff0c;用到循环就可以把整个过程分成多个循环体&#xff0c;就是每一次循环要执行的内容。 反转链表&#xff1a; 把null–>1…

OpenFegin

文章目录 一、OpenFegin是什么&#xff1f;二、基本使用三、超时重试机制4.自定义超时重传机制五、底层实现 一、OpenFegin是什么&#xff1f; OpenFeign的全称为Spring Cloud OpenFeign(下文简称OpenFeign),是Spring Cloud团队开发的一款基于 Feign的框架&#xff0c;声明式W…

『网络游戏』Tips弹窗队列【10】

修改脚本&#xff1a;DynamicWnd.cs 修改脚本&#xff1a;GameRoot.cs 运行项目 - Tips提示消息按顺序依次弹出显示 修改代码&#xff1a;GameRoot.cs 修改代码&#xff1a;LoginSys.cs 运行项目 设置初始化函数 将CreateWnd设置为隐藏 运行项目 本章结束

Python爬虫之正则表达式于xpath的使用教学及案例

正则表达式 常用的匹配模式 \d # 匹配任意一个数字 \D # 匹配任意一个非数字 \w # 匹配任意一个单词字符&#xff08;数字、字母、下划线&#xff09; \W # 匹配任意一个非单词字符 . # 匹配任意一个字符&#xff08;除了换行符&#xff09; [a-z] # 匹配任意一个小写字母 […

【斯坦福CS144】Lab3

一、实验目的 完成 TCPSender 的四个接口。 二、实验内容 在该实验中&#xff0c;我们需要完成 TCPSender 的以下四个接口&#xff1a; **fill_window&#xff1a;**TCPSender 从 ByteStream 中读取数据&#xff0c;并以 TCPSegement 的形式发送&#xff0c;尽可能地填充接…

多端同步的收银系统源码

随着经济的不断发展&#xff0c;很多门店越来越趋向连锁品牌化&#xff0c;收银系统自然也成为很多连锁门店必不可少的软件工具。希望通过一套软件可以帮助门店解决门店线下销售、会员管理、连锁多门店管理、线下线上一体化、商品库存管理等难题实现降本增效&#xff0c;为了方…