The following forum(s) are migrating to a new home on Microsoft Q&A (Preview): Developing Universal Windows apps!

Ask new questions on Microsoft Q&A (Preview).
Interact with existing posts until December 13, 2019, after which content will be closed to all new and existing posts.

Learn More

 locked
[UWP]WritableBitmap in Universal Windows RRS feed

  • Question

  • I have an UWP application and I want to take a number of bitmap images and place them into one before using an Image control to render to the screen. I have identified that the WriteableBitmap class is the way to go but I have a couple of problems.

    1). I cannot get VS to recognise a number of the calls (i.e writePixels method)

    2. The Int32Rect is not recognised and so causes errors.

    3). It seems a little heavy handed to have to copy all the pixels form one image to then have to individual paste them into the other, is they a better way?

    Does anybody have any ideas to solve this .

    Thanks


    • Moved by Andy ONeill Sunday, December 6, 2015 10:55 PM wrong forum
    • Edited by Krunal Parekh Tuesday, December 8, 2015 7:43 AM subject
    Sunday, December 6, 2015 7:19 PM

Answers

  • Hi Cairn,

    For your first and second questions, it is because Windows.UI.Xaml.Media.Imaging namespace doesn't provide a `WritePixels` method, and there is no 'Int32Rect' method too. Here can you see the APIs for Bitmap in an UWP app: https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.media.imaging.aspx?f=255&MSPPError=-2147217396

    For the last question, I don't know which is the better way to do this, there should be many ways to do it. I just wrote a simple demo to do this, which use a `RenderTargetBitmap` to combine pictures together. And this method to combine the pictures is much easier for me.

    xaml code:

        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="3*"/>
                    <RowDefinition Height="3*"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                
                <Button Content="Select first image" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="0" Grid.Row="0" Width="170" Click="SelectImage1"/>
                <Button Content="Select second image" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="1" Grid.Row="0" Width="170" Click="SelectImage2"/>
    
                <StackPanel x:Name="combinedimg" Grid.Row="1" Grid.ColumnSpan="2" Orientation="Horizontal">
                    <Image x:Name="img1" Grid.Row="1" Grid.Column="0" Stretch="Fill"  />
                    <Image x:Name="img2" Grid.Row="1" Grid.Column="1" Stretch="Fill"  />
                </StackPanel>
    
                <StackPanel Grid.Row="2" Grid.ColumnSpan="2" Orientation="Vertical">
                    <Image Name="newimg" Height="300" Margin="0,20,0,0"/>
                    <Button Click="OnClick" Content="Click to combine the images" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="0,20,0,0"/>
                </StackPanel>
            </Grid>
        </Grid>

    .cs code:

            public MainPage()
            {
                this.InitializeComponent();
            }
    
            private async void SelectImage1(object sender, RoutedEventArgs e)
            {
                FileOpenPicker picker = new FileOpenPicker();
                picker.FileTypeFilter.Add(".jpg");
                picker.FileTypeFilter.Add(".tif");
                picker.FileTypeFilter.Add(".png");
                picker.FileTypeFilter.Add(".jpeg");
    
                StorageFile file = await picker.PickSingleFileAsync();
                if (file != null)
                {
                    var bitmap = new BitmapImage();
                    var stream = await file.OpenReadAsync();
                    await bitmap.SetSourceAsync(stream);
                    img1.Source = bitmap;
                }
    
            }
    
            private async void SelectImage2(object sender, RoutedEventArgs e)
            {
                FileOpenPicker picker = new FileOpenPicker();
                picker.FileTypeFilter.Add(".jpg");
                picker.FileTypeFilter.Add(".tif");
                picker.FileTypeFilter.Add(".png");
                picker.FileTypeFilter.Add(".jpeg");
    
                StorageFile file = await picker.PickSingleFileAsync();
                if (file != null)
                {
                    var bitmap = new BitmapImage();
                    var stream = await file.OpenReadAsync();
                    await bitmap.SetSourceAsync(stream);
                    img2.Source = bitmap;
                }
            }
    
            private async void OnClick(object sender, RoutedEventArgs e)
            {
                RenderTargetBitmap renderbmp = new RenderTargetBitmap();
                await renderbmp.RenderAsync(combinedimg);
                this.newimg.Source = renderbmp;
            }
        }

    This demo is just used to choose two pictures from files, show them in one `StackPanel`, and combine them into one picture and show this new picture. You can change the style how the selected pictures be showed through changing the layout of this `StackPanel`, you can also change the code to select more than two pictures.

    Wish this can help you.

    Best regards

    Grace



    • Edited by Grace Feng Monday, December 7, 2015 6:31 AM wrong spelt
    • Proposed as answer by Krunal Parekh Thursday, December 17, 2015 2:47 AM
    • Marked as answer by Krunal Parekh Thursday, December 17, 2015 2:52 AM
    Monday, December 7, 2015 6:29 AM

All replies

  • I don't know if it is what you're looking for, but I wrote a blog post recently about how to turn a XAML control (with images and text) into a .PNG image to then use as a live tile image. You should be able to use the code to do what you want:

    http://blog.grogansoft.com/

    Basically, you create a XAML user control with whatever visual content you want, then render it as an image. My code saves a .PNG to the app folder. Then you can do anything you want with that image (I add it to a live tile, you could simply display it).


    Visit http://blog.grogansoft.com/ for Windows development fun.

    Monday, December 7, 2015 4:58 AM
  • Hi Cairn,

    For your first and second questions, it is because Windows.UI.Xaml.Media.Imaging namespace doesn't provide a `WritePixels` method, and there is no 'Int32Rect' method too. Here can you see the APIs for Bitmap in an UWP app: https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.media.imaging.aspx?f=255&MSPPError=-2147217396

    For the last question, I don't know which is the better way to do this, there should be many ways to do it. I just wrote a simple demo to do this, which use a `RenderTargetBitmap` to combine pictures together. And this method to combine the pictures is much easier for me.

    xaml code:

        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="3*"/>
                    <RowDefinition Height="3*"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                
                <Button Content="Select first image" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="0" Grid.Row="0" Width="170" Click="SelectImage1"/>
                <Button Content="Select second image" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="1" Grid.Row="0" Width="170" Click="SelectImage2"/>
    
                <StackPanel x:Name="combinedimg" Grid.Row="1" Grid.ColumnSpan="2" Orientation="Horizontal">
                    <Image x:Name="img1" Grid.Row="1" Grid.Column="0" Stretch="Fill"  />
                    <Image x:Name="img2" Grid.Row="1" Grid.Column="1" Stretch="Fill"  />
                </StackPanel>
    
                <StackPanel Grid.Row="2" Grid.ColumnSpan="2" Orientation="Vertical">
                    <Image Name="newimg" Height="300" Margin="0,20,0,0"/>
                    <Button Click="OnClick" Content="Click to combine the images" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="0,20,0,0"/>
                </StackPanel>
            </Grid>
        </Grid>

    .cs code:

            public MainPage()
            {
                this.InitializeComponent();
            }
    
            private async void SelectImage1(object sender, RoutedEventArgs e)
            {
                FileOpenPicker picker = new FileOpenPicker();
                picker.FileTypeFilter.Add(".jpg");
                picker.FileTypeFilter.Add(".tif");
                picker.FileTypeFilter.Add(".png");
                picker.FileTypeFilter.Add(".jpeg");
    
                StorageFile file = await picker.PickSingleFileAsync();
                if (file != null)
                {
                    var bitmap = new BitmapImage();
                    var stream = await file.OpenReadAsync();
                    await bitmap.SetSourceAsync(stream);
                    img1.Source = bitmap;
                }
    
            }
    
            private async void SelectImage2(object sender, RoutedEventArgs e)
            {
                FileOpenPicker picker = new FileOpenPicker();
                picker.FileTypeFilter.Add(".jpg");
                picker.FileTypeFilter.Add(".tif");
                picker.FileTypeFilter.Add(".png");
                picker.FileTypeFilter.Add(".jpeg");
    
                StorageFile file = await picker.PickSingleFileAsync();
                if (file != null)
                {
                    var bitmap = new BitmapImage();
                    var stream = await file.OpenReadAsync();
                    await bitmap.SetSourceAsync(stream);
                    img2.Source = bitmap;
                }
            }
    
            private async void OnClick(object sender, RoutedEventArgs e)
            {
                RenderTargetBitmap renderbmp = new RenderTargetBitmap();
                await renderbmp.RenderAsync(combinedimg);
                this.newimg.Source = renderbmp;
            }
        }

    This demo is just used to choose two pictures from files, show them in one `StackPanel`, and combine them into one picture and show this new picture. You can change the style how the selected pictures be showed through changing the layout of this `StackPanel`, you can also change the code to select more than two pictures.

    Wish this can help you.

    Best regards

    Grace



    • Edited by Grace Feng Monday, December 7, 2015 6:31 AM wrong spelt
    • Proposed as answer by Krunal Parekh Thursday, December 17, 2015 2:47 AM
    • Marked as answer by Krunal Parekh Thursday, December 17, 2015 2:52 AM
    Monday, December 7, 2015 6:29 AM
  • Thanks for that, it appears Microsoft could be sued for miss representation with this API class. The set of documents it appears I was looking at was for WPF which contains 3 variants of a WritePixels method.  

    This means the solution I need is going to be more complex, I have a number of images (6GB's) which can all be joined together could form one image (map and sections of a map), but since I which to keep the memory foot print down I only load the sections I am bothered about. Using the stream method I am going to have to do a line at a time in order that the image appears seamless, Thanks Microsoft.

    Monday, December 7, 2015 7:29 PM
  • Sue the zoo!
    Thursday, January 7, 2016 1:00 AM