sgonchar
Topic Author
Posts: 33
Joined: 15 Mar 2021, 22:11

Showing downloaded / web images

16 Jun 2021, 00:16

Hello,
I'm wondering about how it's best to display downloaded images.

Currently we show images via something like this:
<Rectangle.Fill>
        <ImageBrush ImageSource="../Art/foo.png" />
</Rectangle.Fill>

<ImageBrush ImageSource="bar.png" />
Trying to overwrite the .png asset with downloaded data is possible but not optimal as we want to vary the number of images.
Ultimate goal is to be able to render basic text interlaced with some images ala patch notes or news article.

1) Does a tag/component exist that already fetches an image from url?
2) Is there an example of how to display png data that is already downloaded in a new texture/space?
2.1) Here you gave a great example of how to manually display dynamic text, is there a way to handle images the same?
3) Do you have some thoughts on a good way of doing something like this?
3.1) is there an example in demos?
4) Do you plan to support image fetching in #1963 ?
4.1) #1963 is slated for 3.0.13 now, that puts ETA sometime in July?

edit: 5) Does markup like this support images? https://www.noesisengine.com/docs/Gui.C ... orial.html
 
User avatar
jsantos
Site Admin
Posts: 3147
Joined: 20 Jan 2012, 17:18
Contact:

Re: Showing downloaded / web images

17 Jun 2021, 01:47

1) Does a tag/component exist that already fetches an image from url?
2) Is there an example of how to display png data that is already downloaded in a new texture/space?
We don't have that by default. I think the best approach for doing this is implementing your own texture provider and then handle all requests on your side. You can have your own cache implemented this way. Please, let me know if you need help with this.
2.1) Here you gave a great example of how to manually display dynamic text, is there a way to handle images the same?
3) Do you have some thoughts on a good way of doing something like this?
3.1) is there an example in demos?
5) Does markup like this support images? https://www.noesisengine.com/docs/Gui.C ... orial.html
Images can be inlined using <InlineUIContainer>. For example:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Background="White">
    <TextBlock x:Name="txt" Width="225" VerticalAlignment="Center" TextWrapping="Wrap"
        FontFamily="Fonts/#Roboto" Foreground="Black" FontSize="20">
        <Run>Lorem ipsum dolor sit amet, consectetur adipiscing</Run>
        <InlineUIContainer>
            <Image Source="Images/camera.png" Stretch="None"/>
        </InlineUIContainer>
        <Run>elit. Donec consequat, justo sit amet</Run>
        <Run>consectetur mattis, nisi</Run>
        <InlineUIContainer>
            <Button x:Name="btn" Content="{Binding Text, ElementName=btnText}"/>
        </InlineUIContainer>
        <Run>eros consectetur enim, volutpat facilisis orci elit ut risus.</Run>
    </TextBlock>
    <StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Margin="20" TextElement.FontSize="30" TextElement.Foreground="Black">
        <TextBlock x:Name="btnText" Text="Button"/>
        <TextBlock Text="{Binding FontSize, ElementName=btn}"/>
    </StackPanel>
</Grid>
4) Do you plan to support image fetching in #1963 ?
I think image fetching is something that should be implemented externally with a texture provider. But we definitely should improve #1963 with support for inlining images. What do you think?
4.1) #1963 is slated for 3.0.13 now, that puts ETA sometime in July?
Yes, sorry about the delay. NoesisGUI 3.1 is taking a bit more than expected, today we released the first public version and having the final 3.1 before GDC21 is our priority right now. But, we will try to have #1963 solved also.

Please, let me know if you need more detail in any of my answers.
 
sgonchar
Topic Author
Posts: 33
Joined: 15 Mar 2021, 22:11

Re: Showing downloaded / web images

17 Jun 2021, 02:51

Thank you for the answers!

It's likely best if we implement our own image download / texture provider.

Using your example with InlineUIContainer works great in preview and run time when in xaml files. Thank you!

For runtime updates, I tried:
Noesis::TextBlock* pTextBlock = FindName<Noesis::TextBlock>("TesterCard2");
mTextBlock->SetText(" Some foo ");
However, that just shows tags as text and doesn't parse things.
I found several posts like this and like this, about how to use InlineCollection and tried this:
Noesis::InlineCollection* pInlines = pTextBlock->GetInlines();
    pInlines->Clear();
    std::string strTester = "Some text before  <InlineUIContainer> <Image Source = \"foo.png\" Width = \"200\" Height = \"100\"  Stretch = \"UniformToFill\" /></InlineUIContainer> some text after";
    pInlines->Add(Noesis::MakePtr<Noesis::Run>( strTester ));
but it's doing the same thing as SetText, tags show up as text, they aren't parsed.

Am I missing some kind of .pareseNow() / .commit() / .process() ?
I'm not going via a binding yet (doing it right in component initialization) that might be the problem .. I'll try binding next.
 
User avatar
sfernandez
Site Admin
Posts: 2255
Joined: 22 Dec 2011, 19:20

Re: Showing downloaded / web images

17 Jun 2021, 10:12

Hi, the idea of #1963 is that you set the text you want to parse in a property of the behavior:
<TextBlock>
  <i:Interaction.Behaviors>
    <local:RichTextFormatterBehavior RichText="{Binding TextToParse}"/>
  </i:Interaction.Behaviors>
</TextBlock>
The behavior will have a PropertyChangedCallback for the RichText property that will parse the string and build the inlines on the associated TextBlock. Those inlines could be simple Runs, but also Hyperlinks or InlineUIContainers with images.

So you can't directly set the formatted text in the TextBlock, you need to parse it and generate the individual inlines, like the following pseudo-code:
Token[] tokens = StringUtils.Parse(richText);
foreach (Token token in tokens)
{
  switch (token.type)
  {
    caseTokenType.Run:
      textBlock.Inlines.Add(new Run(token.text));
      break;
    case TokenType.Bold:
      Bold bold = new Bold();
      bold.Inlines.Add(new Run(token.text));
      textBlock.Inlines.Add(bold);
      break;
    case TokenType.Hyperlink:
      Hyperlink hyperlink = new Hyperlink { NavigateUri = token.text };
      hyperlink.Inlines.Add(new Run(token.text));
      textBlock.Inlines.Add(hyperlink);
      break;
    case TokenType.Image:
      Image image = new Image { Source = token.image };
      InlineUIContainer container = new InlineUIContainer { Child = image };
      textBlock.Inlines.Add(container);
      break;
    ...
   }
 }
I hope this makes things clearer.
 
User avatar
sfernandez
Site Admin
Posts: 2255
Joined: 22 Dec 2011, 19:20

Re: Showing downloaded / web images

17 Jun 2021, 11:27

Thinking a bit more about this, the easiest (and less verbose) way to provide this is using an attached property, and is how we plan to implement #1963.
<TextBlock noesis:Text.RichText="This is an [b]example[/b] of rich text"/>
 
sgonchar
Topic Author
Posts: 33
Joined: 15 Mar 2021, 22:11

Re: Showing downloaded / web images

17 Jun 2021, 21:07

Hello,
That sounds great, if RichText will support basic html and images that would be wonderful.

Before that happens, I've been trying to get it to run via inline containers. There's still a possibly that:
- we'll need to add custom components (like progress bar on image loading)
- that we may not be able to save a downloaded png in local storage (say switch is very picky on it) and may need to insert textures from memory. However, I can't find an example where that's done in your demos? Is it possible to create textrue / textrueProvider / BitmapImage directly from memory?

I got the text formatting to show, but images don't show up, would you be able to say why?
  //  <TextBlock x:Name="TesterCard">
  //      Some text1
  //      <Bold>Bold text</Bold> 
  //      <InlineUIContainer>
  //          <Image Source="foo.png" />
  //      </InlineUIContainer>
  //  </TextBlock>    // Shows up great when in xaml
      
    Noesis::TextBlock* pTextBlock = FindName<Noesis::TextBlock>("TesterCard2");

    //////////////////////// Text
    Noesis::InlineCollection* pInlines = pTextBlock->GetInlines();
    pInlines->Clear();
    pInlines->Add(Noesis::MakePtr<Noesis::Run>( "Some text1") ); // Don't put tags inside

    Noesis::Bold* boldText = new Noesis::Bold();
    Noesis::InlineCollection* boldInlines = boldText->GetInlines(); 
    boldInlines->Add(new Noesis::Run("Bold text"));
    pInlines->Add( Noesis::MakePtr<Noesis::Bold>(boldText) );  // Shows up bold

    //////////////////////// Images
    Noesis::ImageSource* pImageSrcFromBitmap2 = new Noesis::BitmapImage("foo.png");
    Noesis::Image* image = new Noesis::Image();
    image->SetSource( pImageSrcFromBitmap2 );
    Noesis::InlineUIContainer* inlineUIContaier = new Noesis::InlineUIContainer();
    inlineUIContaier->SetChild(image);
    pInlines->Add( Noesis::MakePtr<Noesis::InlineUIContainer>(inlineUIContaier) );  // Does not show :(
When in xaml adding <TextBlock><InlineUIContainer><Image ... >>> in inspector it shows the image under TextBlock, there is no InlineUIContainer.
When doing the above, inspector shows an empty InlineUIContainer under TextBlock, no Image ... when I'd expect these two to match.
 
User avatar
sfernandez
Site Admin
Posts: 2255
Joined: 22 Dec 2011, 19:20

Re: Showing downloaded / web images

18 Jun 2021, 10:55

Hi, the problem is with this line:
Noesis::MakePtr<Noesis::InlineUIContainer>(inlineUIContaier)
It is creating a new InlineUIContainer using the following constructor and passing the previously created container, not the image:
InlineUIContainer(UIElement* child)
Just a few tips about reference counting as described here, if you use new and don't Release the reference after setting the object in a property, you will be leaking memory. It is preferable that you create objects with MakePtr and use Ptr to automatically manage object references. Your code should look like this:
//////////////////////// Text
Noesis::InlineCollection* pInlines = txt->GetInlines();
pInlines->Clear();
pInlines->Add(Noesis::MakePtr<Noesis::Run>("Some text1")); // Don't put tags inside

Noesis::Ptr<Noesis::Bold> boldText = Noesis::MakePtr<Noesis::Bold>();
boldText->GetInlines()->Add(Noesis::MakePtr<Noesis::Run>("Bold text"));
pInlines->Add(boldText);  // Shows up bold

//////////////////////// Images
Noesis::Ptr<Noesis::Image> image = Noesis::MakePtr<Noesis::Image>();
image->SetSource(Noesis::MakePtr<Noesis::BitmapImage>("foo.png"));
pInlines->Add(Noesis::MakePtr<Noesis::InlineUIContainer>(image));
I hope this helps.
 
User avatar
jsantos
Site Admin
Posts: 3147
Joined: 20 Jan 2012, 17:18
Contact:

Re: Showing downloaded / web images

18 Jun 2021, 13:22

That sounds great, if RichText will support basic html and images that would be wonderful.
The implementation is going to be relatively basic, as that's something not part of core. Just support for bold, italic and images. Probably you will need to tweak and improve the implementation for you needs.
- that we may not be able to save a downloaded png in local storage (say switch is very picky on it) and may need to insert textures from memory. However, I can't find an example where that's done in your demos? Is it possible to create textrue / textrueProvider / BitmapImage directly from memory?
The provider must return a Texture object. You decide how to create it, you don't need to store the image in local storage if you don't need to. Please, have a look at our FileTextureProvider, as it is a good example about creating textures. Note though, that the implementation is not the most efficient, because the texture is not being compressed, so you probably want to create your own native (for D3D11, D3D12, GL...) texture and then Wrap it into Noesis. All our renderers provide a Wrap function for that purpose (for example, have a look at D3D11Factory.h).
static Noesis::Ptr<Noesis::Texture> WrapTexture(ID3D11Texture2D* texture, uint32_t width, uint32_t height, uint32_t levels, bool isInverted, bool hasAlpha);

Who is online

Users browsing this forum: No registered users and 3 guests