Operation is not supported - embedding image

Hi,

I'm trying to embed an image on Android, and I can get it to compile, but at runtime, I get System.NotSupportedException "Operation is not supported." when calling xls.AddImage (from adapted ApiMate code).

Here is the relevant code:

using (Stream fs = Assets.Open ("images/logo.png", Android.Content.Res.Access.Streaming))
{
    TImageProperties ImgProps = new TImageProperties();
    ImgProps.LockAspectRatio = true;
    ImgProps.Anchor = new TClientAnchor(TFlxAnchorType.MoveAndResize, 25, 88, 1, 0, 25, 238, 1, 1024);
    ImgProps.ShapeName = "logo.png";
    xls.AddImage(fs, ImgProps);
}



I did change the FileStream object to a Stream object, but it does compile, and it seems like it should work.
 Is that incorrect?

Kevin N.

The problem is that the stream returned by Assets.Open isn't seekable, you can't go back and forth on it, only read forward. AddImage (and most stuff really) needs seekable streams.


The solution is simple, even if a little wasteful in memory: Copy the fs stream to a memory stream, and use that to insert the image.

We have some examples of this in our demos, for example in LangWars- MainActivity.cs we do:

            ExcelFile Result = new XlsFile(true);
            using(var template = Assets.Open("report.template.xls"))
            {
                //we can't load directly from the asset stream, as we need a seekable stream.
                using (var memtemplate = new MemoryStream())
                {
                    template.CopyTo(memtemplate);
                    memtemplate.Position = 0;
                    Result.Open(memtemplate);
                }
            }
 
The same idea applies here, and with most streams you get from Assets.Open. You'll need to copy them to a memorystream first.

Regards,
   Adrian.

Awesome! I that that worked - though I don't have access to my actual device to be sure. Thanks for the info, and the solution!

I ended up doing this:

//we can't load directly from the asset stream, as we need a seekable stream.
using (var template = Assets.Open ("images/logo.png")) {
    using (var fs = new MemoryStream ()) {
        template.CopyTo (fs);
        TImageProperties ImgProps = new TImageProperties ();
        ImgProps.LockAspectRatio = true;
        ImgProps.Anchor = new TClientAnchor (TFlxAnchorType.MoveAndResize, 25, 88, 1, 0, 25, 238, 1, 1024);
        ImgProps.ShapeName = "logo.png";
        xls.AddImage (fs, ImgProps);
    }
}

Actually that didn't work. I'm just getting a blank spot where the image should be.

Hi,

I think you are missing the line:
fs.Position = 0;

After the CopyTo. If you leave the memory stream at the end, it will be an empty image.

I had the line number off by 10 or so, and just didn't see it down there. Sorry about that. Thanks for your awesome support!