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
FrameIndex
but how would I use it since it used forGetPixels()
notDecode()
. - There are no properties, I found, that control
FrameIndex
within aSKBitmap
. - The additional conversion from
Image
toXImage
is a bit confusing as from the source here, it appears to be a constructor that creates anXImage
straight from anImage
. I would need to create anXImage
from aSkiaSharp.SKBitmap
instead 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
SKBitmap
withdisposes the
inStream
.Anyway, to get the particular frame using SkiaSharp, you need to get pixels from the codec: