首页 文章

通过RenderAsync()创建和保存图像不适用于从Windows Phone 8.1中随机选择的图像

提问于
浏览
0

我正在为Windows Phone 8.1开发一个小游戏,为此我使用一组图像路径并选择一个并将其作为网格的背景并使用 RenderAsync() 生成位图并将其保存到设备的图片文件夹中 .

我的图像路径是正确的,我在XAML中使用以下代码来创建UI

<StackPanel>
    <Grid x:Name="ResultGrid" Margin="0,-26.667,0,-0.333" Visibility="Visible">
        <Grid.Background>
            <ImageBrush Stretch="Fill" ImageSource="Assets/result/b (3).png"/>
        </Grid.Background>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200*"/>
            <ColumnDefinition Width="200*"/>
        </Grid.ColumnDefinitions>
        <StackPanel x:Name="SuperHeroName" Margin="71,262,-22,212" Grid.Column="1">
            <StackPanel.Background>
                <ImageBrush Stretch="Fill" ImageSource="Assets/result/h (10).png"/>
            </StackPanel.Background>
        </StackPanel>
        <TextBlock x:Name="txtResultSharing" Margin="14,259,107,12" Grid.ColumnSpan="2" FontSize="48" Text="I have earned 78555 points in 8000 levels" TextWrapping="WrapWholeWords" Foreground="#FFA2A2A2" FontFamily="Buxton Sketch"/>
        <Image x:Name="AppLogo" Margin="130,586,10,2" Grid.Column="1" Source="/Assets/FULL LOGO.png"/>
        <TextBlock x:Name="txtResultSharing1" Margin="12,257,109,14" Grid.ColumnSpan="2" FontSize="48" Text="I have earned 78555 points in 8000 levels" TextWrapping="WrapWholeWords" Foreground="White" FontFamily="Buxton Sketch"/>
    </Grid>
</StackPanel>

而代码是

private async void boom()
{
    Random rnd = new Random();
    string[] heroImages = { "ms-appx:///Assets/result/h (1).png", 
                        "ms-appx:///Assets/result/h (2).png", 
                        "ms-appx:///Assets/result/h (3).png", 
                        "ms-appx:///Assets/result/h (4).png", 
                        "ms-appx:///Assets/result/h (5).png", 
                        "ms-appx:///Assets/result/h (6).png",
                        "ms-appx:///Assets/result/h (7).png",
                        "ms-appx:///Assets/result/h (8).png",
                        "ms-appx:///Assets/result/h (9).png",
                        "ms-appx:///Assets/result/h (10).png",
                        "ms-appx:///Assets/result/h (11).png",
                        "ms-appx:///Assets/result/h (12).png",
                        "ms-appx:///Assets/result/h (13).png",
                        "ms-appx:///Assets/result/h (14).png",
                        "ms-appx:///Assets/result/h (15).png",
                        "ms-appx:///Assets/result/h (16).png",
                        "ms-appx:///Assets/result/h (17).png",
                        "ms-appx:///Assets/result/h (18).png",
                        "ms-appx:///Assets/result/h (19).png",
                        "ms-appx:///Assets/result/h (20).png",
                        "ms-appx:///Assets/result/h (21).png",
                        "ms-appx:///Assets/result/h (22).png",
                        "ms-appx:///Assets/result/h (23).png" };
    var imageBrushT = new ImageBrush
    {
        ImageSource = new BitmapImage(new Uri(heroImages[rnd.Next(22)]))
    };
    SuperHeroName.Background = imageBrushT;

    string[] backImages = { "ms-appx:///Assets/result/b (1).png", 
                        "ms-appx:///Assets/result/b (2).png", 
                        "ms-appx:///Assets/result/b (3).png", 
                        "ms-appx:///Assets/result/b (5).png", 
                        "ms-appx:///Assets/result/b (6).png" };
    var imageBrushX = new ImageBrush
    {
        ImageSource = new BitmapImage(new Uri(backImages[rnd.Next(5)]))
    };
    ResultGrid.Background = imageBrushX;

    ResultGrid.UpdateLayout();


    int x = int.Parse(localSettings.Values["CurrLevel"].ToString());
    int y = int.Parse(localSettings.Values["CurrPoints"].ToString());
    txtResultSharing.Text = string.Format("I have earned {0} points in {1} levels", y.ToString(), x.ToString());
    txtResultSharing1.Text = string.Format("I have earned {0} points in {1} levels", y.ToString(), x.ToString());
    ResultGrid.Visibility = Visibility.Visible;
    ResultGrid.UpdateLayout();
    RenderTargetBitmap renderTargetBitmapZ = new RenderTargetBitmap();
    await renderTargetBitmapZ.RenderAsync(ResultGrid);
    var pixels = await renderTargetBitmapZ.GetPixelsAsync();            

    var file = await KnownFolders.PicturesLibrary.CreateFileAsync("picresult.jpg", CreationCollisionOption.ReplaceExisting);

    using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
    {
        var encoder = await
            BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
        byte[] bytes = pixels.ToArray();
        encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                             BitmapAlphaMode.Ignore,
                             (uint)renderTargetBitmapZ.PixelWidth,
                             (uint)renderTargetBitmapZ.PixelHeight,
                             96, 96, bytes);
        await encoder.FlushAsync();
    }
}

当我按下显示按钮时,此代码在显示屏中显示正确的图像,当我打开并看到没有超级英雄图像和背景图像时显示的已保存图像(即picresult.jpg)文件时,显示正确的图像 . 它仅显示徽标和文本 . (即,它不会保存从数组中随机选择的图像,但它会显示它们没有任何问题)

请帮我

1 回答

  • 2

    问题是您正在尝试在创建可能尚未绘制的图像后立即将网格渲染到位图 . 事实上,因为你看到它看起来像他们没有 .
    在构建类时预加载图像:

    heroImages = new BitmapImage[3];
    heroImages[0] = new BitmapImage(new Uri("ms-appx:///Assets/Image1.png"));
    heroImages[1] = new BitmapImage(new Uri("ms-appx:///Assets/Image2.jpg"));
    heroImages[2] = new BitmapImage(new Uri("ms-appx:///Assets/Image3.jpg"));
    
    backImages = new BitmapImage[5];
    backImages[0] = new BitmapImage(new Uri("ms-appx:///Assets/Image1.png"));
    backImages[1] = new BitmapImage(new Uri("ms-appx:///Assets/Image2.jpg"));
    backImages[2] = new BitmapImage(new Uri("ms-appx:///Assets/Image3.jpg"));
    backImages[3] = new BitmapImage(new Uri("ms-appx:///Assets/Image1.png"));
    backImages[4] = new BitmapImage(new Uri("ms-appx:///Assets/Image2.jpg"));
    

    将代码移动到一个函数:

    private async Task DrawToFile()
    {
        RenderTargetBitmap renderTargetBitmapZ = new RenderTargetBitmap();
        await renderTargetBitmapZ.RenderAsync(ResultGrid);
        var pixels = await renderTargetBitmapZ.GetPixelsAsync();
    
        var file = await KnownFolders.PicturesLibrary.CreateFileAsync("picresult.jpg", CreationCollisionOption.ReplaceExisting);
    
        using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
        {
            var encoder = await
                BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
            byte[] bytes = pixels.ToArray();
            encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                                 BitmapAlphaMode.Ignore,
                                 (uint)renderTargetBitmapZ.PixelWidth,
                                 (uint)renderTargetBitmapZ.PixelHeight,
                                 96, 96, bytes);
            await encoder.FlushAsync();
        }
    }
    

    然后在Class中的某处设置DispatcherTimer,如下所示:

    DispatcherTimer _timer;  //  member of class
    
    //  Add Following to constructor
    _timer = new DispatcherTimer();
    _timer.Interval = new TimeSpan(0, 0, 1);  // 1 second
    _timer.Tick += _timer_Tick;
    
    //  Timer Routine
    void _timer_Tick(object sender, object e)
    {
        _timer.Stop();
        DrawToFile();
    }
    

    最后在RenderGrid.UpdateLayout()调用后启动计时器:

    txtResultSharing.Text = string.Format("I have earned {0} points in {1} levels", y.ToString(), x.ToString());
    txtResultSharing1.Text = string.Format("I have earned {0} points in {1} levels", y.ToString(), x.ToString());
    ResultGrid.Visibility = Visibility.Visible;
    ResultGrid.UpdateLayout();
    
    _timer.Start();
    

    在您尝试将图像保存到文件之前,这将为UI提供1秒的时间来绘制图像 . 应该管用 .

相关问题