in source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp [275:424]
void XamlBuilder::SetImageOnUIElement(winrt::Uri const& imageUrl,
T const& uiElement,
winrt::AdaptiveCardResourceResolvers const& resolvers,
bool isAutoSize,
winrt::IInspectable const& parentElement,
winrt::IInspectable const& imageContainer,
bool isVisible,
winrt::Stretch stretch)
{
bool mustHideElement = true;
// Get the image url scheme
winrt::hstring schemeName = imageUrl.SchemeName();
// Get the resolver for the image
if (resolvers)
{
auto resolver = resolvers.Get(schemeName);
// If we have a resolver
if (resolver)
{
// Create a BitmapImage to hold the image data. We use BitmapImage in order to allow
// the tracker to subscribe to the ImageLoaded/Failed events
winrt::BitmapImage bitmapImage{};
if (!m_enableXamlImageHandling && (m_listeners.size() != 0))
{
this->m_imageLoadTracker->TrackBitmapImage(bitmapImage);
}
bitmapImage.CreateOptions(winrt::BitmapCreateOptions::None);
// Create the arguments to pass to the resolver
auto args = winrt::make<winrt::implementation::AdaptiveCardGetResourceStreamArgs>(imageUrl);
// And call the resolver to get the image stream
auto getResourceStreamOperation = resolver.GetResourceStreamAsync(args);
getResourceStreamOperation.Completed(
[this, weakThis = this->get_weak(), uiElement, bitmapImage, stretch, isAutoSize, parentElement, imageContainer, isVisible](
winrt::IAsyncOperation<winrt::IRandomAccessStream> const& operation, winrt::AsyncStatus status) -> void
{
if (status == winrt::AsyncStatus::Completed)
{
if (auto strongThis = weakThis.get())
{
auto randomAccessStream = operation.GetResults();
if (!randomAccessStream)
{
this->m_imageLoadTracker->MarkFailedLoadBitmapImage(bitmapImage);
return;
}
SetImageSource(uiElement, bitmapImage, stretch);
auto setSourceAction = bitmapImage.SetSourceAsync(randomAccessStream);
setSourceAction.Completed(
[weakThis, uiElement, isAutoSize, parentElement, imageContainer, isVisible](
winrt::IAsyncAction const&, winrt::AsyncStatus status)
{
if (status == winrt::AsyncStatus::Completed && isAutoSize)
{
if (auto strongThis = weakThis.get())
{
strongThis->SetAutoSize(uiElement, parentElement, imageContainer, isVisible, false /* imageFiresOpenEvent */);
}
}
});
}
}
else
{
if (auto strongThis = weakThis.get())
{
this->m_imageLoadTracker->MarkFailedLoadBitmapImage(bitmapImage);
}
}
});
}
}
if (schemeName == L"data")
{
// Decode base 64 string
winrt::hstring dataPath = imageUrl.Path();
std::string data = AdaptiveBase64Util::ExtractDataFromUri(HStringToUTF8(dataPath));
std::vector<char> decodedData = AdaptiveBase64Util::Decode(data);
winrt::DataWriter dataWriter{winrt::InMemoryRandomAccessStream{}};
dataWriter.WriteBytes(std::vector<byte>{decodedData.begin(), decodedData.end()});
winrt::BitmapImage bitmapImage{};
bitmapImage.CreateOptions(winrt::BitmapCreateOptions::IgnoreImageCache);
m_imageLoadTracker->TrackBitmapImage(bitmapImage);
auto streamWriteOperation = dataWriter.StoreAsync();
streamWriteOperation.Completed(
[weakThis = this->get_weak(), dataWriter, bitmapImage, uiElement, isAutoSize, parentElement, imageContainer, isVisible](
winrt::IAsyncOperation<uint32_t> const& /*operation*/, winrt::AsyncStatus /*status*/) -> void
{
if (auto strongThis = weakThis.get())
{
if (const auto stream = dataWriter.DetachStream().try_as<winrt::InMemoryRandomAccessStream>())
{
stream.Seek(0);
strongThis->SetImageSource(uiElement, bitmapImage);
auto setSourceAction = bitmapImage.SetSourceAsync(stream);
setSourceAction.Completed(
[weakThis, bitmapImage, isAutoSize, parentElement, imageContainer, isVisible](
winrt::IAsyncAction const& /*operation*/, winrt::AsyncStatus status)
{
if (status == winrt::AsyncStatus::Completed && isAutoSize)
{
if (auto strongThis = weakThis.get())
{
strongThis->SetAutoSize(bitmapImage, parentElement, imageContainer, isVisible, false /* imageFiresOpenEvent */);
}
}
});
}
}
});
m_writeAsyncOperations.push_back(streamWriteOperation);
mustHideElement = false;
return;
}
// Otherwise, no resolver...
if ((m_enableXamlImageHandling) || (m_listeners.size() == 0))
{
// If we've been explicitly told to let Xaml handle the image loading, or there are
// no listeners waiting on the image load callbacks, use Xaml to load the images
winrt::BitmapImage bitmapImage{};
bitmapImage.UriSource(imageUrl);
SetImageSource(uiElement, bitmapImage, stretch);
if (isAutoSize)
{
SetAutoSize(uiElement, parentElement, imageContainer, isVisible, true /* imageFiresOpenEvent */);
}
}
else
{
PopulateImageFromUrlAsync(imageUrl, uiElement);
}
}