Как сделать <image>в фоновом процессе WPF? - PullRequest
3 голосов
/ 09 января 2009

Я беру Silverlight XAML и отправляю его в веб-службу, которая отображает XAML в потоке STA и генерирует изображение PNG. Все XAML отображаются правильно, кроме <image> записей, которые «появляются» для правильной загрузки, когда их свойство Source установлено в WPF, но PNG не показывает ссылочное изображение - что я делаю неправильно?

Суть кода, который я использую, приведена ниже. Объект value - это DTO от Silverlight, который содержит XAML в строке, которая заканчивается как локальное свойство sXAML, а URI изображения находится в свойстве value.ImageURL.

  var canvas = (FrameworkElement)XamlReader.Load(new XmlTextReader(new StringReader(sXAML)));

  var obj = canvas.FindName("BGImage");
  Image img = null;
  if (obj != null)
  {
    img = obj as Image;
    img.ImageFailed += img_ImageFailed;
    img.Source = new BitmapImage(new Uri(value.ImageURL, UriKind.Absolute));
  }

  canvas.Arrange(new Rect(new Size(463d, 381d)));
  canvas.UpdateLayout();

  var mem = new MemoryStream();
  var bmp = new RenderTargetBitmap(463, 381, 96d, 96d, PixelFormats.Pbgra32);
  bmp.Render(canvas);

  var encoder = new PngBitmapEncoder();
  encoder.Frames.Add(BitmapFrame.Create(bmp));
  encoder.Save(mem);

  FileStream fs = new FileStream("D:\\out.png", FileMode.Create);
  mem.WriteTo(fs);
  fs.Close();

NB. Обработчик события img_ImageFailed никогда не вызывается, что указывает на то, что назначение источника img каким-то образом было успешным.

1 Ответ

2 голосов
/ 26 января 2009

Вещи, которые я бы попробовал:

1) Если в вашем приложении WPF вы «визуализируете» динамически загруженную Canvas для отображения в окне, все ли это работает (включая изображения)?

2) Вы пытались подключить обработчик Loaded к объекту img, чтобы увидеть , когда изображение действительно загружено?

3) Предполагается, что работает # 1 - где находятся изображения (находятся ли они в Интернете / на локальном веб-сервере)? Если вы установите точку останова в коде на

bmp.Render(canvas);

и подождать некоторое время, прежде чем наступить - изображение затем появится в отрендеренном выводе?

Я подозреваю, что изображение загружается асинхронно, и вы визуализируете Canvas слишком рано, пока объект Image не определил свой источник.

[ОБНОВЛЕНИЕ 29-Jan-09] возможное решение

Я точно скопировал твой код и попробовал. Когда я использовал «локальное» расположение изображения (например, «c: \ images \ splash.jpg»), изображение выводилось в формате jpeg. Когда я использовал URL (например, "http://localhost/images/splash.jpg"), он НЕ появлялся (как вы описываете).

Таким образом, я изменил ваш код следующим образом (чтобы попытаться принудительно загрузить изображение - будет работать только для http: ссылки на изображения) -

if (obj != null)
{
    img = obj as Image;
    // new stuff
    BitmapImage bi = new BitmapImage();
    bi.BeginInit();
    bi.StreamSource = getCachedURLStream(new Uri(ImageURL));
    bi.EndInit();
    img.BeginInit();
    img.Source = bi;
    img.EndInit();
    //img.ImageFailed += img_ImageFailed;
    //img.Loaded += new RoutedEventHandler(img_Loaded);
    //img.Source = new BitmapImage(new Uri(ImageURL, UriKind.Absolute));
}
public static Stream getCachedURLStream(Uri url)
{
    HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(url);
    WebResponse response;
    webrequest.CachePolicy = new RequestCachePolicy(RequestCacheLevel.Default);
    response = webrequest.GetResponse();
    Stream s = response.GetResponseStream();
    BufferedStream bs = new BufferedStream(s, 8192);
    return bs;
}

(метод getCachedURLStream взят из синхронная загрузка изображений - это немного посторонно, но я просто хотел быстро проверить кусок кода), и он, похоже, сработал (изображение видно в JPEG). Может быть, это будет работать в вашем сценарии?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...