2009-01-09 5 views
3

Je prends Silverlight XAML et l'envoie à un service Web qui rend le XAML dans un thread STA et génère une image PNG. Tout le rendu XAML correctement, sauf les <image> entrées qui «apparaissent» pour charger correctement lorsque leur propriété Source est définie dans WPF mais le PNG n'affiche pas l'image référencée - qu'est-ce que je fais mal?Comment rendre un <image> dans un processus WPF en arrière-plan?

Le cœur du code que j'utilise est le suivant. L'objet value est un objet DTO de Silverlight qui contient le code XAML dans la chaîne qui se termine par la propriété locale sXAML et l'image URI par la propriété 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: Le gestionnaire d'événements img_ImageFailed est jamais appelé indiquant que la cession img Source a réussi en quelque sorte.

+0

Impossible d'obtenir WPF pour rendre l'image d'arrière-plan - ne vous inquiétez pas. J'ai chargé l'image d'arrière-plan dans une image bitmap et l'ai modifiée avec l'image bitmap XAML rendue et générée avec succès l'image désirée. – user22096

Répondre

2

Ce que je voudrais essayer:

1) Dans votre application WPF, si vous rendre votre chargé dynamiquement Canvas pour afficher dans une fenêtre, il fait tout travail (images incluses)?

2) Avez-vous essayé de fixer un gestionnaire Loaded à l'objet img voir quand l'image est effectivement chargée?

3) En supposant que le n ° 1 fonctionne - où sont situées les images (sont-elles sur Internet/serveur web local)? Si vous mettez un point d'arrêt dans le code sur

bmp.Render(canvas); 

et attendre un certain temps avant de monter sur - l'image ne alors apparaissent dans la sortie rendue?

Je suppose que l'image est "téléchargée" de manière asynchrone et que vous rendez le Canvas trop tôt, avant que l'objet Image ait résolu sa source.

[MISE A JOUR 29-Jan-09] solution possible

Je vous codez copié vers le bas exactement et lui a donné un essai. Lorsque j'ai utilisé un emplacement d'image 'local' (par exemple "c: \ images \ splash.jpg") l'image a été rendue bien dans le fichier JPEG de sortie. Lorsque j'ai utilisé une URL (par exemple "http://localhost/images/splash.jpg"), elle n'apparaissait PAS (comme vous le décrivez).

Je modifié votre code comme suit (pour essayer de forcer l'image à télécharger - ne fonctionnera pour http: références d'images) -

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; 
} 

(la méthode getCachedURLStream est de synchronous image loading - c'est un peu superflue mais je voulais juste un morceau de code rapide à tester) et il semblait alors fonctionner (image visible en JPEG). Peut-être que cela fonctionnera dans votre scénario?

+0

Si vous ne convertissez pas le retour de WebRequest.Create (url) en HttpWebRequest, cela fonctionnera pour les adresses locales ("file: // c: /foo.png") ou en apparence nouveau Uri ("@" C: \ temp \ foo.png "). A noter également: le webrequest.La ligne CachePolicy est requise, au moins dans le contexte j'ai besoin de cette correction. – sphereinabox

Questions connexes