【问题标题】:WriteableBitmap.Savejpeg does not render grid text (image is OK)WriteableBitmap.Savejpeg 不渲染网格文本(图像正常)
【发布时间】:2013-02-01 14:47:12
【问题描述】:

我在用户控件中有一个网格:

<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneAccentBrush}">
    <Image 
        x:Name="imgBack"
        Opacity=".25" />
    <Grid VerticalAlignment="Top" HorizontalAlignment="Left">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <!-- Some textblocks -->
</Grid>

网格大小和图像来源在运行时动态设置:

public void ChangeSizeAndImage(int width, int height, string backImagePath)
{
    // Set the height and width
    LayoutRoot.Width = width;
    LayoutRoot.Height = height;

    // Set the background image
    imgBack.Source = new BitmapImage(new Uri(backImagePath, UriKind.RelativeOrAbsolute));

    this.UpdateLayout();
}

然后我调用一个从 ui 元素生成 jpeg 并将其保存到 IsolatedStorage 的方法(稍后添加到 Windows Phone Live Tile)

public static Uri CreateImageFromUIElement(UIElement element, int width, int height)
{
    // Instance to store the image in
    IsolatedStorageFile userStore = IsolatedStorageFile.GetUserStoreForApplication();

    // Random ID to use for the file name
    string id = Guid.NewGuid().ToString("n");

    // create directory to read/write from
    const string shellContentDirectory = "Shared\\ShellContent";
    userStore.CreateDirectory(shellContentDirectory);

    // Render the UIElement into a writeable bitmap
    WriteableBitmap bitmap = new WriteableBitmap(element, new CompositeTransform());

    // Save the bitmap to a file. This stream must be closed in order to be read later
    string imagePath = shellContentDirectory + "\\" + id + ".jpg";
    using (IsolatedStorageFileStream stream = userStore.OpenFile(imagePath, System.IO.FileMode.Create))
    {
        bitmap.SaveJpeg(stream, width, height, 0, 100);
    }

    // Uri to get us to the image
    Uri imageUri = new Uri("isostore:/" + imagePath.Replace('\\', '/'));
    return imageUri;
}

我能够成功使用磁贴上的图像,但我只看到黑色背景的图像,而看不到任何文字。我认为这与 jpeg 和透明 PNG 有关,但是,我在上面的 Grid 上设置了背景颜色,所以我不确定为什么它会被认为是透明的。

编辑 1 我正在以编程方式初始化此用户控件,设置一些属性,并将其传递给 create image 方法。我发现如果我将此用户控件添加到页面,然后使用调用创建图像方法,它工作得很好。一定有一些关于它在页面上呈现的东西,导致所有东西都正确排列。不幸的是,这种方法在我的情况下是不可能的。有什么步骤可以让这个工作吗?控件上的UpdateLayout(); 不起作用。

【问题讨论】:

    标签: wpf silverlight windows-phone-7 writeablebitmap


    【解决方案1】:

    您遇到了以后台方式呈现 XAML 的巨大挑战。在最终意识到它是什么之前,我在同一个问题上跑来跑去。更糟糕的是,每隔一段时间它就可以正常工作!

    问题在于图像的加载方式。创建控件时,会创建 Image 元素,并将图像加载/解码启动到另一个线程。与此同时,您的线程继续运行。您将控件渲染到一个文件并保存它,片刻之后(这是您看不到的部分)图像完成加载,并进行实际渲染。好郁闷!

    你不能只是拖延时间,因为你不知道需要多长时间(而且我不确定它是否会那样工作。你要做的就是将你的工作分成多个部分,并订阅 Image 上的 ImageOpened 事件。当事件触发时,您可以相信一切正常并保存位图。

    在后台代理中,这很棘手,因为您需要推迟调用 NotifyComplete() 直到那时,当然图像可能由于多种原因而无法加载。为了完整起见,您还需要订阅 ImageFailed 事件并处理它!

    在 WP8 应用程序中,您应该使用 async/await 模式来简化整个流程。在 WP7 中,您需要自己同步事物。如果你需要,我可以发布一些代码。

    我希望我能为您提供一个更简单的解决方案,但希望这会让您朝着正确的方向前进!

    【讨论】:

      【解决方案2】:

      这对我有用:

      UserControl myControl = new UserControl();
      myControl.Arrange(new Rect(0, 0, Width, Height));
      
      WriteableBitmap writeable = new WriteableBitmap(Width, Height);
      Writeable.Render(Control, null);
      writeable.Invalidate();
      
      IsolatedStorageFileStream fileStream = myIsolatedStorage.CreateFile("/Shared/ShellContent/" + Filename);
      
      System.Windows.Media.Imaging.Extensions.SaveJpeg(writeable, fileStream, Width, Height, 0, 100);
      fileStream.Close();
      

      希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 2017-08-17
        • 1970-01-01
        • 2013-04-04
        • 2011-07-21
        • 1970-01-01
        • 2021-10-30
        • 2014-07-26
        • 2019-04-22
        • 2013-10-23
        相关资源
        最近更新 更多