Downloading Images from URLs in C++

May 5, 2024 ยท 12 min read

Introduction

Downloading images from URLs is a common task in many C++ applications, whether it's for image processing, computer vision, or building multimedia applications.

C++ provides several powerful libraries and techniques to make image downloading a breeze.

In this article, we'll explore five different methods to download images from URLs, complete with code examples.

By the end of this article, you'll have a solid understanding of how to download images efficiently using C++. ๐Ÿ’ช

Prerequisites

Before we dive in, make sure you have the following:

  • C++ compiler installed on your system (e.g., GCC, Clang, or Visual Studio).
  • Basic knowledge of C++ programming.
  • Familiarity with command-line compilation and linking.
  • Now, let's explore the five ways to download images from URLs using C++! ๐Ÿš€

    Method 1: Using libcurl

    libcurl is a popular and feature-rich library for making HTTP requests and handling URL transfers.

    It provides a simple and efficient way to download images from URLs.

    Here's an example of downloading an image using libcurl:

    #include <iostream>
    #include <fstream>
    #include <curl/curl.h>
    
    size_t writeData(void* ptr, size_t size, size_t nmemb, FILE* stream) {
        size_t written = fwrite(ptr, size, nmemb, stream);
        return written;
    }
    
    int main() {
        std::string url = "<https://example.com/image.jpg>";
        std::string filename = "downloaded_image.jpg";
    
        CURL* curl = curl_easy_init();
        if (curl) {
            FILE* fp = fopen(filename.c_str(), "wb");
            curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
            CURLcode res = curl_easy_perform(curl);
            curl_easy_cleanup(curl);
            fclose(fp);
    
            if (res != CURLE_OK) {
                std::cout << "Failed to download image: " << curl_easy_strerror(res) << std::endl;
            } else {
                std::cout << "Image downloaded successfully: " << filename << std::endl;
            }
        }
    
        return 0;
    }
    

    In this example:

    1. We include the necessary headers: for console output, for file I/O, and for libcurl functionality.
    2. We define a callback function writeData that writes the received data to a file stream.
    3. In the main function, we specify the URL of the image we want to download and the filename to save it as.
    4. We initialize a CURL object using curl_easy_init().
    5. We open the file in binary write mode using fopen().
    6. We set the URL option using curl_easy_setopt(curl, CURLOPT_URL, url.c_str()).
    7. We set the write function and data options using curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData) and curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp).
    8. We perform the request using curl_easy_perform(curl) and check the result.
    9. We clean up the CURL object and close the file.

    libcurl provides a powerful and flexible way to download images from URLs, with support for various protocols and advanced options.

    Method 2: Using Boost.Asio

    Boost.Asio is a cross-platform C++ library for network programming.

    It provides a high-level interface for making asynchronous HTTP requests and handling responses.

    Here's an example of downloading an image using Boost.Asio:

    #include <iostream>
    #include <fstream>
    #include <boost/asio.hpp>
    #include <boost/asio/ssl.hpp>
    
    using boost::asio::ip::tcp;
    
    int main() {
        std::string url = "<https://example.com/image.jpg>";
        std::string filename = "downloaded_image.jpg";
    
        boost::asio::io_context io_context;
        boost::asio::ssl::context ssl_context(boost::asio::ssl::context::sslv23);
        tcp::resolver resolver(io_context);
        tcp::resolver::results_type endpoints = resolver.resolve("example.com", "https");
    
        boost::asio::ssl::stream<tcp::socket> socket(io_context, ssl_context);
        boost::asio::connect(socket.lowest_layer(), endpoints);
        socket.handshake(boost::asio::ssl::stream_base::client);
    
        boost::asio::streambuf request;
        std::ostream request_stream(&request);
        request_stream << "GET " << url << " HTTP/1.1\\r\\n";
        request_stream << "Host: " << "example.com" << "\\r\\n";
        request_stream << "Accept: */*\\r\\n";
        request_stream << "Connection: close\\r\\n\\r\\n";
    
        boost::asio::write(socket, request);
    
        boost::asio::streambuf response;
        boost::asio::read_until(socket, response, "\\r\\n");
    
        std::istream response_stream(&response);
        std::string http_version;
        response_stream >> http_version;
        unsigned int status_code;
        response_stream >> status_code;
        std::string status_message;
        std::getline(response_stream, status_message);
    
        if (status_code != 200) {
            std::cout << "Failed to download image. Status code: " << status_code << std::endl;
            return 1;
        }
    
        boost::asio::read_until(socket, response, "\\r\\n\\r\\n");
        std::string header;
        while (std::getline(response_stream, header) && header != "\\r")
            ;
    
        std::ofstream output_file(filename, std::ios::binary);
        if (!output_file) {
            std::cout << "Failed to create output file." << std::endl;
            return 1;
        }
    
        boost::system::error_code error;
        while (boost::asio::read(socket, response, boost::asio::transfer_at_least(1), error)) {
            output_file << &response;
        }
    
        if (error != boost::asio::error::eof) {
            std::cout << "Failed to download image: " << error.message() << std::endl;
        } else {
            std::cout << "Image downloaded successfully: " << filename << std::endl;
        }
    
        return 0;
    }
    

    In this example:

    1. We include the necessary headers: for console output, for file I/O, and and for Boost.Asio functionality.
    2. We specify the URL of the image we want to download and the filename to save it as.
    3. We create an io_context and ssl_context for handling the HTTPS connection.
    4. We resolve the host and establish a secure connection using boost::asio::ssl::stream.
    5. We prepare the HTTP request by constructing the request headers.
    6. We send the request using boost::asio::write(socket, request).
    7. We read the response status code and headers using boost::asio::read_until() and parse them.
    8. If the status code is not 200 (OK), we exit with an error message.
    9. We create an output file stream and read the image data from the response using boost::asio::read().
    10. We write the image data to the output file.
    11. We check for any errors during the download process and print the appropriate message.

    Boost.Asio provides a powerful and flexible way to download images from URLs, with support for asynchronous operations and secure connections.

    Method 3: Using Qt Network Module

    Qt is a cross-platform application framework that provides a rich set of libraries for building graphical user interfaces and network applications.

    The Qt Network module offers classes for making HTTP requests and handling network operations.

    Here's an example of downloading an image using the Qt Network module:

    #include <QCoreApplication>
    #include <QNetworkAccessManager>
    #include <QNetworkRequest>
    #include <QNetworkReply>
    #include <QUrl>
    #include <QFile>
    #include <QDebug>
    
    int main(int argc, char* argv[]) {
        QCoreApplication app(argc, argv);
    
        QString url = "<https://example.com/image.jpg>";
        QString filename = "downloaded_image.jpg";
    
        QNetworkAccessManager manager;
        QNetworkRequest request(QUrl(url));
        QNetworkReply* reply = manager.get(request);
    
        QObject::connect(reply, &QNetworkReply::finished, [=]() {
            if (reply->error() == QNetworkReply::NoError) {
                QFile file(filename);
                if (file.open(QIODevice::WriteOnly)) {
                    file.write(reply->readAll());
                    file.close();
                    qDebug() << "Image downloaded successfully:" << filename;
                } else {
                    qDebug() << "Failed to create output file.";
                }
            } else {
                qDebug() << "Failed to download image:" << reply->errorString();
            }
    
            reply->deleteLater();
            app.quit();
        });
    
        return app.exec();
    }
    

    In this example:

    1. We include the necessary headers from the Qt framework: for the application object, and for network operations, for handling the network response, for URL handling, for file I/O, and for debugging output.
    2. We create a QCoreApplication object to handle the application's event loop.
    3. We specify the URL of the image we want to download and the filename to save it as.
    4. We create a QNetworkAccessManager object to manage the network request.
    5. We create a QNetworkRequest object with the image URL.
    6. We send a GET request using manager.get(request) and store the reply in a QNetworkReply object.
    7. We connect the finished signal of the reply to a lambda function that handles the response.
    8. In the lambda function, we check if there are no errors in the reply.
    9. If there are no errors, we create a QFile object and open it in write mode.
    10. We write the image data from the reply to the file using reply->readAll() and close the file.
    11. If there are errors, we print an error message using qDebug().
    12. We delete the reply object and quit the application.

    The Qt Network module provides a convenient and object-oriented approach to downloading images from URLs, with built-in support for asynchronous operations and error handling.

    Method 4: Using OpenCV

    OpenCV (Open Source Computer Vision Library) is a popular library for computer vision and image processing.

    It also provides functionality for downloading images from URLs.

    Here's an example of downloading an image using OpenCV:

    #include <opencv2/opencv.hpp>
    #include <iostream>
    
    int main() {
        std::string url = "<https://example.com/image.jpg>";
        std::string filename = "downloaded_image.jpg";
    
        cv::Mat image = cv::imread(url, cv::IMREAD_COLOR);
    
        if (image.empty()) {
            std::cout << "Failed to download image." << std::endl;
            return 1;
        }
    
        cv::imwrite(filename, image);
    
        std::cout << "Image downloaded successfully: " << filename << std::endl;
    
        return 0;
    }
    

    In this example:

    1. We include the necessary header: for OpenCV functionality.
    2. We specify the URL of the image we want to download and the filename to save it as.
    3. We use cv::imread() to download and read the image from the URL, specifying the color mode as cv::IMREAD_COLOR.
    4. We check if the image is empty, indicating a failure to download the image.
    5. If the image is not empty, we save it to a file using cv::imwrite().
    6. We print a success message if the image is downloaded and saved successfully.

    OpenCV provides a simple and convenient way to download images from URLs, especially if you're already using OpenCV for image processing tasks.

    Method 5: Using Poco Libraries

    Poco is a collection of C++ libraries for building network-centric and internet-based applications.

    It provides a Net library that includes classes for making HTTP requests and handling network operations.

    Here's an example of downloading an image using the Poco libraries:

    #include <Poco/Net/HTTPClientSession.h>
    #include <Poco/Net/HTTPRequest.h>
    #include <Poco/Net/HTTPResponse.h>
    #include <Poco/StreamCopier.h>
    #include <Poco/Path.h>
    #include <Poco/URI.h>
    #include <Poco/Exception.h>
    #include <iostream>
    #include <fstream>
    
    using namespace Poco::Net;
    using namespace Poco;
    
    int main() {
        std::string url = "<https://example.com/image.jpg>";
        std::string filename = "downloaded_image.jpg";
    
        try {
            URI uri(url);
            std::string path(uri.getPathAndQuery());
            if (path.empty()) {
                path = "/";
            }
    
            HTTPClientSession session(uri.getHost(), uri.getPort());
            HTTPRequest request(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
            HTTPResponse response;
    
            session.sendRequest(request);
            std::istream& rs = session.receiveResponse(response);
    
            if (response.getStatus() == HTTPResponse::HTTP_OK) {
                std::ofstream ofs(filename, std::ios::binary);
                StreamCopier::copyStream(rs, ofs);
                std::cout << "Image downloaded successfully: " << filename << std::endl;
            } else {
                std::cout << "Failed to download image. HTTP response status: " << response.getStatus() << std::endl;
            }
        } catch (Exception& ex) {
            std::cout << "Exception occurred: " << ex.displayText() << std::endl;
        }
    
        return 0;
    }
    

    In this example:

    1. We include the necessary headers from the Poco libraries: for HTTP client functionality, and for HTTP request and response handling, for stream copying, and for path and URI handling, and for exception handling.
    2. We specify the URL of the image we want to download and the filename to save it as.
    3. We create a Poco::URI object from the URL to extract the host, port, and path.
    4. We create an HTTPClientSession object with the host and port.
    5. We create an HTTPRequest object with the HTTP GET method and the path.
    6. We send the request using session.sendRequest(request).
    7. We receive the response using session.receiveResponse(response).
    8. If the response status is HTTP_OK (200), we create an output file stream and use StreamCopier::copyStream() to copy the response stream to the file.
    9. If the response status is not HTTP_OK, we print an error message.
    10. We catch any exceptions that may occur during the download process and print the exception message.

    The Poco libraries provide a comprehensive and flexible way to download images from URLs, with support for various network protocols and error handling.

    Choosing the Right Method

    With several options available for downloading images in C++, you might be wondering which method to choose.

    Consider the following guidelines:

  • If you need a simple and widely-used library for downloading images, libcurl is a great choice. It is easy to use and provides a lot of flexibility.
  • If you're working with asynchronous programming and need a high-performance library, Boost.Asio is a powerful option. It allows you to handle multiple downloads efficiently.
  • If you're developing a Qt application and want seamless integration with the Qt framework, the Qt Network module is a natural choice. It provides an object-oriented approach to network programming.
  • If you're already using OpenCV for computer vision tasks and need to download images as part of your pipeline, using OpenCV's built-in functionality can simplify your code.
  • If you require a comprehensive and feature-rich library for network programming, the Poco libraries offer a wide range of classes and utilities for downloading images and handling network operations.
  • Ultimately, the choice depends on your specific requirements, project constraints, and familiarity with the libraries.

    Conclusion

    You now have a solid understanding of various ways to download images from URLs using C++.

    Whether you prefer the simplicity of libcurl, the asynchronous power of Boost.Asio, the integration with Qt, the convenience of OpenCV, or the comprehensive features of Poco, C++ provides you with diverse options to suit your needs.

    Remember to handle errors gracefully, validate the downloaded images, and consider factors like performance, scalability, and maintainability when choosing a method.

    Browse by tags:

    Browse by language:

    The easiest way to do Web Scraping

    Get HTML from any page with a simple API call. We handle proxy rotation, browser identities, automatic retries, CAPTCHAs, JavaScript rendering, etc automatically for you


    Try ProxiesAPI for free

    curl "http://api.proxiesapi.com/?key=API_KEY&url=https://example.com"

    <!doctype html>
    <html>
    <head>
        <title>Example Domain</title>
        <meta charset="utf-8" />
        <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
    ...

    X

    Don't leave just yet!

    Enter your email below to claim your free API key: