Исходник Гайд ImGui загрузка raw изображений из интернета.

артём диджитал дизайнер
Участник
Статус
Оффлайн
Регистрация
10 Окт 2020
Сообщения
490
Реакции[?]
477
Поинты[?]
66K
Всем привет, супер быстрый гайд (спать уже пора).

Когда я только начинал всю эту движуху с имгуем и плюсами в целом - эта тема меня очень интересовала, поэтому я решил показать самый простейший пример.
Здесь не будет использоваться всяких curl`ов и прочего, чистый wininet, поэтому парить голову для установки 100500 библиотек вам не нужно.
Таргет - DirectX 11, но переписать под вашу платформу можно очень просто (для тех кто совсем не тут - можете написать в телегу, перепишу под ваш directx)

Что нужно для использования?
1 - DirectX девайс
2 - Ссылка на "сырую" картинку, пример - откройте любое изображение в Discord и нажмите "Открыть в браузере", это и есть сырое изображение и ссылка на него.

ImageLoader.hpp:
#ifndef IMAGE_LOADER_HPP
#define IMAGE_LOADER_HPP

#if _HAS_CXX17
#include <string_view>
#else
#include <string>
#endif

#include <d3d11.h>

class ImageLoader {
public:
#if _HAS_CXX17
    using string_t = std::string_view;
#else
    using string_t = const std::string&;
#endif

    ImageLoader() = default;
    ImageLoader(ID3D11Device* dx_device, string_t image_url);
    ~ImageLoader();

    /* Same as ImageLoader constructor just might be called later */
    void initialize(ID3D11Device* dx_device, string_t image_url);

    /* Get image instance */
    ID3D11ShaderResourceView* image() const noexcept;

private:;
    ID3D11ShaderResourceView* m_image;
};

#endif
ImageLoader.cpp:
#include "ImageLoader.hpp"

#include <Windows.h>
#include <wininet.h>
#include <vector>
#include <stdexcept>
#include <memory>
#include <d3dx11.h>

#pragma comment(lib, "d3dx11.lib")
#pragma comment(lib, "wininet.lib")

#define MAX_FILESIZE_TO_READ 4096

ImageLoader::ImageLoader(ID3D11Device* dx_device, string_t image_url) : m_image(nullptr)
{
    if (m_image != nullptr)
        return;

    initialize(dx_device, image_url);
}

ImageLoader::~ImageLoader() {}

void ImageLoader::initialize(ID3D11Device* dx_device, string_t image_url)
{
    if (m_image != nullptr)
        return;

    std::unique_ptr<std::remove_pointer_t<HINTERNET>, decltype(&InternetCloseHandle)>
        hInternet(InternetOpenA("ImGui ImageLoader", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0), InternetCloseHandle);

    if (!hInternet) {
        throw std::runtime_error("InternetOpenA failed");
    }

    std::unique_ptr<std::remove_pointer_t<HINTERNET>, decltype(&InternetCloseHandle)>
        hURL(InternetOpenUrlA(hInternet.get(), image_url.data(), NULL, 0, INTERNET_FLAG_RELOAD, 0), InternetCloseHandle);

    if (!hURL) {
        throw std::runtime_error("InternetOpenUrl failed");
    }

    std::vector<BYTE> image_data;
    std::vector<BYTE> buffer(MAX_FILESIZE_TO_READ); // Why the heap and not the stack? Because that's the way i want it.
    DWORD bytes_read = 0;
    while (InternetReadFile(hURL.get(), buffer.data(), MAX_FILESIZE_TO_READ, &bytes_read) && bytes_read > 0) {
        image_data.insert(image_data.end(), buffer.data(), buffer.data() + bytes_read);
    }

    D3DX11_IMAGE_LOAD_INFO image_load_info;
    ID3DX11ThreadPump* thread_pump{ nullptr };
    HRESULT hr = D3DX11CreateShaderResourceViewFromMemory(dx_device, image_data.data(), image_data.size(), &image_load_info, thread_pump, &m_image, 0);
    if (FAILED(hr)) {
        throw std::runtime_error("D3DX11CreateShaderResourceViewFromMemory failed");
    }
}

ID3D11ShaderResourceView* ImageLoader::image() const noexcept 
{ 
    return m_image; 
}
Пример использования:
1701823686166.png
1701823705285.png

Результат:

1701823773533.png
 
Последнее редактирование:
эксперт в майнкрафт апи
Read Only
Статус
Оффлайн
Регистрация
25 Янв 2023
Сообщения
684
Реакции[?]
286
Поинты[?]
21K
Всем привет, супер быстрый гайд (спать уже пора).

Когда я только начинал всю эту движуху с имгуем и плюсами в целом - эта тема меня очень интересовала, поэтому я решил показать самый простейший пример.
Здесь не будет использоваться всяких curl`ов и прочего, чистый wininet, поэтому парить голову для установки 100500 библиотек вам не нужно.
Таргет - DirectX 11, но переписать под вашу платформу можно очень просто (для тех кто совсем не тут - можете написать в телегу, перепишу под ваш directx)

Что нужно для использования?
1 - DirectX девайс
2 - Ссылка на "сырую" картинку, пример - откройте любое изображение в Discord и нажмите "Открыть в браузере", это и есть сырое изображение и ссылка на него.

ImageLoader.hpp:
class ImageLoader {
public:
    ImageLoader() = default;
    ImageLoader(ID3D11Device* dx_device, const std::string& image_url);
    ~ImageLoader();

    /* Same as ImageLoader constructor just might be called later */
    void initialize(ID3D11Device* dx_device, const std::string& image_url);

    /* Get image instance */
    ID3D11ShaderResourceView* image() const noexcept;

private:;
    ID3D11ShaderResourceView* m_image;
};
ImageLoader.cpp:
#include "ImageLoader.hpp"

#include <Windows.h>
#include <wininet.h>
#include <vector>
#include <stdexcept>
#include <memory>
#include <d3dx11.h>

#pragma comment(lib, "d3dx11.lib")
#pragma comment(lib, "wininet.lib")

#define MAX_FILESIZE_TO_READ 4096

ImageLoader::ImageLoader(ID3D11Device* dx_device, const std::string& image_url) : m_image(nullptr)
{
    if (m_image != nullptr)
        return;

    initialize(dx_device, image_url);
}

ImageLoader::~ImageLoader() {}

void ImageLoader::initialize(ID3D11Device* dx_device, const std::string& image_url)
{
    if (m_image != nullptr)
        return;

    std::unique_ptr<std::remove_pointer_t<HINTERNET>, decltype(&InternetCloseHandle)>
        hInternet(InternetOpenA("ImGui ImageLoader", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0), InternetCloseHandle);

    if (!hInternet) {
        throw std::runtime_error("InternetOpenA failed");
    }

    std::unique_ptr<std::remove_pointer_t<HINTERNET>, decltype(&InternetCloseHandle)>
        hURL(InternetOpenUrlA(hInternet.get(), image_url.c_str(), NULL, 0, INTERNET_FLAG_RELOAD, 0), InternetCloseHandle);

    if (!hURL) {
        throw std::runtime_error("InternetOpenUrl failed");
    }

    std::vector<BYTE> image_data;
    std::vector<BYTE> buffer(MAX_FILESIZE_TO_READ); // Why the heap and not the stack? Because that's the way i want it.
    DWORD bytes_read = 0;
    while (InternetReadFile(hURL.get(), buffer.data(), MAX_FILESIZE_TO_READ, &bytes_read) && bytes_read > 0) {
        image_data.insert(image_data.end(), buffer.data(), buffer.data() + bytes_read);
    }

    D3DX11_IMAGE_LOAD_INFO image_load_info;
    ID3DX11ThreadPump* thread_pump{ nullptr };
    HRESULT hr = D3DX11CreateShaderResourceViewFromMemory(dx_device, image_data.data(), image_data.size(), &image_load_info, thread_pump, &m_image, 0);
    if (FAILED(hr)) {
        throw std::runtime_error("D3DX11CreateShaderResourceViewFromMemory failed");
    }
}

ID3D11ShaderResourceView* ImageLoader::image() const noexcept
{
    return m_image;
}
Пример использования:
Посмотреть вложение 265368
Посмотреть вложение 265369

Результат:

Посмотреть вложение 265370
а почему кеш не статичный
 
Участник
Статус
Оффлайн
Регистрация
5 Окт 2017
Сообщения
784
Реакции[?]
173
Поинты[?]
11K
Пользователь
Статус
Оффлайн
Регистрация
8 Апр 2022
Сообщения
644
Реакции[?]
102
Поинты[?]
65K
Сверху Снизу