介绍与 Conan 2 兼容的全新 Conan Visual Studio 扩展
我们很高兴地宣布发布适用于 Visual Studio 的全新 Conan 扩展,现在完全与 Conan 2 兼容。此扩展旨在简化使用 Visual Studio(2022 及更高版本)和 Conan 的 C++ 开发人员的工作流程。本文将通过一个实际示例指导您使用该扩展:从互联网下载图像、加载图像,并将其作为 ASCII 艺术显示在控制台中。为此,我们将使用以下库,这些库在 Conan Center 中可用
扩展概述
适用于 Visual Studio 的 Conan 扩展为在 IDE 中管理 C++ 包提供了无缝集成,无需外部配置或终端命令。以下是开始使用的方法
安装
直接在 Visual Studio 中安装 Conan 扩展
- 导航到扩展 > 管理扩展。
- 在在线市场中搜索“Conan”。
- 单击下载按钮,然后按照安装提示操作。
- 重新启动 Visual Studio 以激活扩展。
创建新的 C++ 项目
安装 Conan 扩展后,首先在 Visual Studio 中创建一个新的 C++ 项目。让我们创建一个名为 **Image2ASCII** 的新C++ 控制台应用程序项目。
配置扩展
首先,通过转到视图 > 其他窗口 > Conan C/C++ 包管理器启动扩展,并将其停靠在您方便访问的位置,例如解决方案资源管理器旁边。
首次使用时,通过单击⚙️(齿轮)符号在 Conan 工具窗口中配置 Conan 可执行文件路径。您可以指定自定义路径(例如,用于虚拟环境)或使用系统范围的安装。
设置 Conan 可执行文件的有效路径后,搜索框将被启用,我们就可以开始搜索 Conan 包并将它们添加到我们的项目中。
添加所需的依赖项
现在,让我们开始将依赖项添加到项目中,并编写我们的 ASCII 艺术生成器代码。
首先,请添加 libcurl 依赖项以下载图像
- 打开 Conan 工具窗口并搜索
libcurl
。 - 选择所需的版本,然后单击
添加依赖项
将其包含在您的项目中。 - 扩展会自动创建一个
conanfile.py
和conandata.yml
,用于存储依赖项,并在稍后调用MSBuildDeps 生成器在构建之前。 - 在您的项目设置中添加了一个预构建事件,以确保在编译之前安装依赖项。
添加代码
现在,我们准备添加 ASCII 艺术生成器的代码。我们不会深入探讨代码的具体细节,因为这超出了本教程的范围。但是,本示例的所有源代码都在 Conan 2.0 示例库 中提供
打开 Visual Studio 生成的Image2ASCII.cpp 文件,并将示例代码替换为以下代码(您也可以从 库 中复制它)。
#include <iostream>
#include <curl/curl.h>
#include <vector>
#include <string>
#include <fmt/core.h>
#include <fmt/color.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
// Size of ASCII art
static const int new_width = 80;
// Ascii gradient
static const std::string ASCII_CHARS = " .:-=+#%@@@";
// Function to scale the luminance into an ASCII character
char map_luminance_to_ascii(float luminance) {
size_t position = luminance * (ASCII_CHARS.size() - 1);
return ASCII_CHARS[position];
}
// Function to write data from curl call
static size_t write_data(void* ptr, size_t size, size_t nmemb, void* stream) {
((std::string*)stream)->append((char*)ptr, size * nmemb);
return size * nmemb;
}
std::string download_image(const std::string& url) {
CURL* curl = curl_easy_init();
if (!curl) {
std::cerr << "curl init failed" << std::endl;
return "";
}
std::string response_string;
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_string);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // Enable following redirection
// Deactivate SSL verification, just for development!
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
}
curl_easy_cleanup(curl);
return response_string;
}
// Function to convert image to ASCII art
void image_to_ascii(const std::string& image_data) {
int width, height, channels;
unsigned char* data = stbi_load_from_memory(
reinterpret_cast<const stbi_uc*>(image_data.data()),
image_data.size(),
&width,
&height,
&channels,
0
);
if (data == nullptr) {
std::cerr << "Error loading image" << std::endl;
return;
}
// Adjust aspect ratio for ASCII art
int new_height = static_cast<int>(static_cast<double>(height) / width * new_width * 0.45);
for (int i = 0; i < new_height; ++i) {
for (int j = 0; j < new_width; ++j) {
int old_i = i * height / new_height;
int old_j = j * width / new_width;
float r = data[(old_i * width + old_j) * channels + 0] / 255.0f;
float g = data[(old_i * width + old_j) * channels + 1] / 255.0f;
float b = data[(old_i * width + old_j) * channels + 2] / 255.0f;
float luminance = (0.2126f * r + 0.7152f * g + 0.0722f * b);
char ascii_char = map_luminance_to_ascii(luminance);
// Use fmt to print ASCII character with color
fmt::print(fmt::fg(fmt::rgb(uint8_t(r * 255), uint8_t(g * 255), uint8_t(b * 255))), "{}", ascii_char);
}
fmt::print("\n");
}
stbi_image_free(data);
}
int main(int argc, char** argv) {
// Picture by Roshan Kamath from pexels.com
std::string url = "https://images.pexels.com/photos/1661179/pexels-photo-1661179.jpeg";
if (argc > 1) {
url = argv[1]; // Use provided URL if available
}
std::string image_data = download_image(url);
image_to_ascii(image_data);
return 0;
}
本质上,此应用程序将图像 URL 作为参数(如果未提供,则默认为特定 URL),并使用libcurl 的download_image()
函数下载它。随后,它使用stb 读取 RGB 值,并使用image_to_ascii()
函数将亮度值转换为 ASCII 字符,使用fmt 在控制台中打印彩色字符。
编译和执行
像往常一样在 Visual Studio 中构建您的项目。首次构建将触发 Conan 对您的依赖项的安装。每次您添加依赖项或依赖项未针对所选配置安装时,预构建事件将启动 Conan 在构建之前安装依赖项。在项目的首次构建之后,一旦 Conan 安装了所有依赖项,您将必须重新启动构建,以便将所有包含包位置的属性正确注入到项目中。
现在,单击运行按钮启动程序
结论
与 Conan 2 兼容的全新 Conan Visual Studio 扩展旨在为 Conan 包管理器和 Visual Studio IDE 之间提供无缝集成。通过提供一个集成的、直观的界面,它消除了包管理的复杂性,让您专注于应用程序的开发。我们希望此工具能够增强您的开发体验,我们期待着看到您用它构建的内容!