+ LoadImageFromLocalFile(request);
+}
+
+void ResourceThreadImage::Download(const ResourceRequest& request)
+{
+ bool succeeded;
+
+ DALI_LOG_TRACE_METHOD( mLogFilter );
+ DALI_LOG_INFO( mLogFilter, Debug::Verbose, "%s(%s)\n", __FUNCTION__, request.GetPath().c_str() );
+
+ Dali::Vector<uint8_t> dataBuffer;
+ size_t dataSize;
+ succeeded = DownloadRemoteImageIntoMemory( request, dataBuffer, dataSize );
+ if( succeeded )
+ {
+ DecodeImageFromMemory(static_cast<void*>(&dataBuffer[0]), dataBuffer.Size(), request);
+ }
+}
+
+void ResourceThreadImage::Decode(const ResourceRequest& request)
+{
+ DALI_LOG_TRACE_METHOD( mLogFilter );
+ DALI_LOG_INFO(mLogFilter, Debug::Verbose, "%s(%s)\n", __FUNCTION__, request.GetPath().c_str());
+
+ // Get the blob of binary data that we need to decode:
+ DALI_ASSERT_DEBUG( request.GetResource() );
+
+ DALI_ASSERT_DEBUG( 0 != dynamic_cast<Dali::RefCountedVector<uint8_t>*>( request.GetResource().Get() ) && "Only blobs of binary data can be decoded." );
+ Dali::RefCountedVector<uint8_t>* const encodedBlob = reinterpret_cast<Dali::RefCountedVector<uint8_t>*>( request.GetResource().Get() );
+
+ if( 0 != encodedBlob )
+ {
+ const size_t blobSize = encodedBlob->GetVector().Size();
+ uint8_t * const blobBytes = &(encodedBlob->GetVector()[0]);
+ DecodeImageFromMemory(blobBytes, blobSize, request);
+ }
+ else
+ {
+ FailedResource resource(request.GetId(), FailureUnknown);
+ mResourceLoader.AddFailedLoad(resource);
+ }
+}
+
+void ResourceThreadImage::Save(const Integration::ResourceRequest& request)
+{
+ DALI_LOG_TRACE_METHOD( mLogFilter );
+ DALI_ASSERT_DEBUG( request.GetType()->id == ResourceBitmap );
+ DALI_LOG_WARNING( "Image saving not supported on background resource threads." );
+}
+
+bool ResourceThreadImage::DownloadRemoteImageIntoMemory(const Integration::ResourceRequest& request, Dali::Vector<uint8_t>& dataBuffer, size_t& dataSize)
+{
+ bool succeeded = true;
+ CURLcode cresult;
+
+ CURL* curl_handle = curl_easy_init();
+ curl_easy_setopt( curl_handle, CURLOPT_VERBOSE, 0 );
+ curl_easy_setopt( curl_handle, CURLOPT_URL, request.GetPath().c_str() );
+ curl_easy_setopt( curl_handle, CURLOPT_FAILONERROR, 1 );
+
+ // Download header first to get data size
+ char* headerBytes = NULL;
+ size_t headerSize = 0;
+ FILE* header_fp = open_memstream( &headerBytes, &headerSize );
+ double size;
+
+ if( NULL != header_fp)
+ {
+ curl_easy_setopt( curl_handle, CURLOPT_HEADER, 1 );
+ curl_easy_setopt( curl_handle, CURLOPT_NOBODY, 1 );
+ curl_easy_setopt( curl_handle, CURLOPT_WRITEDATA, header_fp );
+
+ cresult = curl_easy_perform( curl_handle );
+ if( cresult == CURLE_OK )
+ {
+ curl_easy_getinfo( curl_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &size );
+ }
+ else
+ {
+ DALI_LOG_WARNING( "Failed to download file to load \"%s\"\n", request.GetPath().c_str() );
+ succeeded = false;
+ }
+
+ fclose( header_fp );
+ }
+ else
+ {
+ succeeded = false;
+ }
+
+ if( NULL != headerBytes )
+ {
+ free( headerBytes );
+ }
+
+ if( succeeded )
+ {
+ // Download file data
+ dataSize = static_cast<size_t>( size );
+ dataBuffer.Reserve( dataSize );
+ dataBuffer.Resize( dataSize );
+
+ Dali::Internal::Platform::FileCloser fileCloser( static_cast<void*>(&dataBuffer[0]), dataSize, "wb" );
+ FILE* data_fp = fileCloser.GetFile();
+ if( NULL != data_fp )
+ {
+ curl_easy_setopt( curl_handle, CURLOPT_HEADER, 0 );
+ curl_easy_setopt( curl_handle, CURLOPT_NOBODY, 0 );
+ curl_easy_setopt( curl_handle, CURLOPT_WRITEDATA, data_fp );
+
+ cresult = curl_easy_perform( curl_handle );
+ if( CURLE_OK != cresult )
+ {
+ DALI_LOG_WARNING( "Failed to download file to load \"%s\"\n", request.GetPath().c_str() );
+ succeeded = false;
+ }
+ }
+ else
+ {
+ succeeded = false;
+ }
+ }
+
+ curl_easy_cleanup( curl_handle );
+
+ if( !succeeded )
+ {
+ FailedResource resource(request.GetId(), FailureUnknown);
+ mResourceLoader.AddFailedLoad(resource);
+ }
+
+ return succeeded;
+}
+
+void ResourceThreadImage::LoadImageFromLocalFile(const Integration::ResourceRequest& request)
+{