推出适用于 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 之间提供无缝集成。通过提供集成的、直观的界面,它消除了包管理的复杂性,让您能够专注于应用程序的开发。我们希望此工具能够增强您的开发体验,并且我们热切期待着看到您用它构建的内容!