add load image from url
This commit is contained in:
@@ -150,6 +150,79 @@ bool Asset::create_dir(const std::string& path)
|
||||
#endif
|
||||
}
|
||||
|
||||
static size_t curl_data_handler_asset(void* contents, size_t size, size_t nmemb, void* userp)
|
||||
{
|
||||
auto buffer = reinterpret_cast<std::vector<uint8_t>*>(userp);
|
||||
buffer->insert(buffer->end(), (char*)contents, (char*)contents + (size * nmemb));
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
static int progress_callback_asset_download(void* clientp, curl_off_t dltotal,
|
||||
curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
|
||||
{
|
||||
Asset* ass = static_cast<Asset*>(clientp);
|
||||
if (ass->m_stop_async)
|
||||
{
|
||||
LOG("interrupt download of %s", ass->m_current_url.c_str());
|
||||
return 1;
|
||||
}
|
||||
float p = dltotal > 0 ? (float)dlnow / (float)dltotal : 0.f;
|
||||
bool cont = ass->on_progress(p);
|
||||
return cont ? 0 : 1;
|
||||
}
|
||||
|
||||
bool Asset::open_url(const std::string& url, std::function<bool(float)> progress /*= nullptr*/)
|
||||
{
|
||||
CURL* curl = curl_easy_init();
|
||||
if (curl)
|
||||
{
|
||||
close();
|
||||
LOG("download %s", url.c_str());
|
||||
m_current_url = url;
|
||||
std::vector<uint8_t> data;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_data_handler_asset);
|
||||
#ifdef __ANDROID__
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
#endif
|
||||
if (progress)
|
||||
{
|
||||
on_progress = progress;
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback_asset_download);
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this);
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
|
||||
}
|
||||
auto err = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (err == CURLE_OK)
|
||||
{
|
||||
if (m_data)
|
||||
delete m_data;
|
||||
m_data = new uint8_t[data.size()];
|
||||
std::copy(data.begin(), data.end(), m_data);
|
||||
m_len = data.size();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::future<bool>& Asset::open_url_async(const std::string& url,
|
||||
std::function<bool(float)> progress /*= nullptr*/, std::function<void(bool)> complete /*= nullptr*/)
|
||||
{
|
||||
close_remote();
|
||||
m_stop_async = false;
|
||||
remote_future = std::async([this, url, progress, complete] {
|
||||
bool ok = open_url(url, progress);
|
||||
if (ok && complete)
|
||||
complete(ok);
|
||||
return ok;
|
||||
});
|
||||
return remote_future;
|
||||
}
|
||||
|
||||
bool Asset::open(const char* path)
|
||||
{
|
||||
//LOG("Asset::open %s", path);
|
||||
@@ -249,3 +322,18 @@ void Asset::close()
|
||||
m_fp = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Asset::close_remote()
|
||||
{
|
||||
if (remote_future.valid())
|
||||
{
|
||||
m_stop_async = true;
|
||||
remote_future.get();
|
||||
}
|
||||
}
|
||||
|
||||
Asset::~Asset()
|
||||
{
|
||||
close_remote();
|
||||
close();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user