0

I am trying to render layout data to a bitmap in a platform-agnostic manner by returning a Splat.IBitmap and am having trouble outputting the results. My WPF platform code looks like this:

MemoryStream stream = new MemoryStream();
try
{
    RenderTargetBitmap target = new RenderTargetBitmap(1024, 1024, 300, 300, PixelFormats.Default);
    PreviewView preview = new PreviewView();  // this does sizing and placement

    target.Render(preview);

    previewViewModel.Dispose();
    BitmapEncoder encoder = new BmpBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create(target));
    encoder.Save(stream);
    stream.Flush();

    IBitmap bitmap = BitmapLoader.Current.Load(stream, 1024, 1024).Result;
    stream.Dispose();

    return bitmap;
}
catch (Exception e)
{
    // TODO: log error
    return null;
}
finally
{
    stream.Dispose();
}

I keep hitting an AggregateException on the BitmapLoader.Current.Load call.The inner exception is a NotSupportedException with the message No imaging component suitable to complete this operation was found. I have not been able to find any relevant documentation to explain what this means or what I'm doing wrong. As a test, I have tried saving the bitmap encoder to a FileStream, which worked fine.

EDIT

It was pointed out that this issue may be a duplicate of this issue. They are certainly related, but in this case I would like to know why saving to the MemoryStream fails to create valid image data where a FileStream works.

EDIT 2

At request, here are the exceptions I see in output:

Exception thrown: 'System.NotSupportedException' in PresentationCore.dll
Exception thrown: 'System.NotSupportedException' in PresentationCore.dll
Exception thrown: 'System.AggregateException' in mscorlib.dll

The inner NotSupportedException of the AggregateException has this message and stacktrace:

No imaging component suitable to complete this operation was found.
at System.Windows.Media.Imaging.BitmapDecoder.SetupDecoderFromUriOrStream(Uri uri, Stream stream, BitmapCacheOption cacheOption, Guid& clsId, Boolean& isOriginalWritable, Stream& uriStream, UnmanagedMemoryStream& unmanagedMemoryStream, SafeFileHandle& safeFilehandle)
at System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri, Uri uri, Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, RequestCachePolicy uriCachePolicy, Boolean insertInDecoderCache)
at System.Windows.Media.Imaging.BitmapImage.FinalizeCreation()
at System.Windows.Media.Imaging.BitmapImage.EndInit()
at Splat.PlatformBitmapLoader.withInit(BitmapImage source, Action`1 block) in y:\\code\\paulcbetts\\splat\\Splat\\Xaml\\Bitmaps.cs:line 80
at Splat.PlatformBitmapLoader.<>c__DisplayClass2.<Load>b__0() in y:\\code\\paulcbetts\\splat\\Splat\\Xaml\\Bitmaps.cs:line 25
at System.Threading.Tasks.Task`1.InnerInvoke()
at System.Threading.Tasks.Task.Execute()

While that exceptions inner NotSupportedException only has this message, and no stack trace:

The component cannot be found. (Exception from HRESULT: 0x88982F50)
Community
  • 1
  • 1
Matt Singer
  • 101
  • 2
  • 10
  • Possible duplicate of ["No imaging component suitable to complete this operation was found."](http://stackoverflow.com/questions/7292764/no-imaging-component-suitable-to-complete-this-operation-was-found) – bradgonesurfing Apr 21 '17 at 05:04
  • Related, but not a duplicate. The root cause of that issue was not being able to download an image and throwing an exception from an invalid image. It's certainly possible that something I'm doing causes my `MemoryStream` to not have valid image data, though as I mentioned it works fine if I use a `FileStream`. If you could point out what my error is, I would appreciate it. – Matt Singer Apr 21 '17 at 15:11
  • Why not set a breakpoint and see where the error is thrown. – bradgonesurfing Apr 22 '17 at 05:28
  • Unfortunately, I'm having trouble figuring out where exactly the exception occurs. The best I can figure out is that it occurs at `source.EndInit();` inside Bitmap.cs, `PlatformBitmapLoader.withInit()`. I can't get any more information out of it. I'm using the nuget version of Splat 1.6.2 and can't debug into it. The best I have is pulling the Splat branch, which isn't exactly the same as the original dll, so my debugging options are limited. – Matt Singer Apr 25 '17 at 03:20
  • Should be the same as the nuget package. https://github.com/paulcbetts/splat/commit/b45e707151d2270c647f91c77af54d4c79ae77ff – bradgonesurfing Apr 25 '17 at 04:58
  • At least post the stack trace in your question. Somebody might be able to figure something out. No point in holding back information. – bradgonesurfing Apr 25 '17 at 04:59
  • stacktraces added – Matt Singer Apr 26 '17 at 00:52
  • Now you can write a test case on SetupDecoderFromUriOrStream with the same arguments it has with your problem. Write a fully repeatable test case along with any associated data/img files and then post it here. – bradgonesurfing Apr 26 '17 at 04:18

1 Answers1

0

This doesn't answer my original question, so I won't accept this as the correct answer, but I found a more correct way to handle what I wanted. I was writing out to a MemoryStream because I thought it was necessary, but all I needed was to take a laid-out view in WPF and get an IBitmap which I could use elsewhere. Turns out making this happen was easier than I was making it out to be:

try
{
    RenderTargetBitmap target = new RenderTargetBitmap(1024, 1024, 300, 300,
        PixelFormats.Default);
    PreviewView preview = new PreviewView();  // this does sizing and placement

    target.Render(preview);

    // HERE IS AN IMPORTANT BIT. This allows me to access the RenderTargetBitmap from 
    // another thread, for example if calling IBitmap.Save() which happens on another
    // in a separate Task
    target.Freeze();

    previewViewModel.Dispose();

    // HERE IS ANOTHER IMPORTANT BIT. There's no need to capture a frame and save to a 
    // Stream through an Encoder. Splat lets you create bitmaps from a native
    // implementation
    IBitmap bitmap = target.FromNative();

    return bitmap;
}
catch (Exception e)
{
    // TODO: log error
    return null;
}
Matt Singer
  • 101
  • 2
  • 10