I am trying to move my code from using System.Drawing.Image to using SkiaSharp as recommended here.
I trying to find similar operations for working with Tif files from a stream.
Currently, the following is what I have using System.Drawing.Image:
System.Drawing.Image MyImage = System.Drawing.Image.FromStream(inStream);
PdfDocument doc = new PdfDocument();
for (int PageIndex = 0; PageIndex < MyImage.GetFrameCount(FrameDimension.Page); PageIndex++)
{
MyImage.SelectActiveFrame(FrameDimension.Page, PageIndex);
XImage img = XImage.FromGdiPlusImage(MyImage);
var page = new PdfPage();
page.Width = MyImage.Width;
page.Height = MyImage.Height;
doc.Pages.Add(page);
XGraphics xgr = XGraphics.FromPdfPage(doc.Pages[PageIndex]);
xgr.DrawImage(img, 0, 0, page.Width, page.Height);
}
doc.Save(outStream);
MyImage.Dispose();
My current work with SkiaSharp is the following though it does not work correctly. Note: The following code has the following error and I am trying to figure out why in addition to how to select active frames: Unhandled exception. System.ObjectDisposedException: Cannot access a closed Stream. likely due to SKCodec codec = SkiaSharp.SKCodec.Create(inStream); but I am not sure why.
PdfDocument doc = new PdfDocument();
doc.Info.CreationDate = new DateTime();
using MemoryStream inStream = new MemoryStream(data);
using var imgStream = new SKManagedStream(inStream, false);
using var skData = SKData.Create(imgStream);
using SKCodec codec = SKCodec.Create(skData);
// TODO: codec is null!
for (int PageIndex = 0; PageIndex < codec.FrameCount; PageIndex++)
{
SKImageInfo imageInfo = new SKImageInfo(codec.Info.Width, codec.Info.Height);
// create bitmap stub
using SKBitmap skBitmap = new SKBitmap(imageInfo);
IntPtr pixelsPtr = skBitmap.GetPixels();
// decode particular frame into the bitmap
codec.GetPixels(imageInfo, pixelsPtr, new SKCodecOptions(PageIndex));
// encode bitmap back
using SKData encodedData = skBitmap.Encode(SKEncodedImageFormat.Png, 100);
using Stream frameStream = encodedData.AsStream();
XImage img = XImage.FromStream(frameStream);
var page = new PdfPage();
doc.Pages.Add(page);
XGraphics xgr = XGraphics.FromPdfPage(doc.Pages[PageIndex]);
xgr.DrawImage(img, 0, 0, page.Width, page.Height);
}
doc.Save(destination);
These are other things I have tried:
- Using SKCodecOptions to set the
FrameIndexbut how would I use it since it used forGetPixels()notDecode(). - There are no properties, I found, that control
FrameIndexwithin aSKBitmap. - The additional conversion from
ImagetoXImageis a bit confusing as from the source here, it appears to be a constructor that creates anXImagestraight from anImage. I would need to create anXImagefrom aSkiaSharp.SKBitmapinstead I believe thought I'm not quite sure how to do this at the moment such as use an existing method likeFromStream()though I don't know the differences between the uses necesarily.
You get the exception because decoding
SKBitmapwithdisposes the
inStream.Anyway, to get the particular frame using SkiaSharp, you need to get pixels from the codec: