Browse Source

wrap stream in skmanagedstream to prevent collection of underlying stream, dispose codec.

pull/3890/head
Dan Walmsley 6 years ago
parent
commit
b08c60bd14
  1. 74
      src/Skia/Avalonia.Skia/ImmutableBitmap.cs

74
src/Skia/Avalonia.Skia/ImmutableBitmap.cs

@ -54,59 +54,59 @@ namespace Avalonia.Skia
Dpi = new Vector(96, 96); Dpi = new Vector(96, 96);
} }
//NOTE: SKCodec.Create randomly crashes when optimizations are enabled.
[MethodImpl(MethodImplOptions.NoOptimization)]
public ImmutableBitmap(Stream stream, int decodeSize, bool horizontal, BitmapInterpolationMode interpolationMode) public ImmutableBitmap(Stream stream, int decodeSize, bool horizontal, BitmapInterpolationMode interpolationMode)
{ {
// create the codec using (var skStream = new SKManagedStream(stream))
var codec = SKCodec.Create(stream); using (var codec = SKCodec.Create(skStream))
var info = codec.Info; {
var info = codec.Info;
// get the scale that is nearest to what we want (eg: jpg returned 512) // get the scale that is nearest to what we want (eg: jpg returned 512)
var supportedScale = codec.GetScaledDimensions(horizontal ? ((float)decodeSize / info.Width) : ((float)decodeSize / info.Height)); var supportedScale = codec.GetScaledDimensions(horizontal ? ((float)decodeSize / info.Width) : ((float)decodeSize / info.Height));
// decode the bitmap at the nearest size // decode the bitmap at the nearest size
var nearest = new SKImageInfo(supportedScale.Width, supportedScale.Height); var nearest = new SKImageInfo(supportedScale.Width, supportedScale.Height);
var bmp = SKBitmap.Decode(codec, nearest); var bmp = SKBitmap.Decode(codec, nearest);
// now scale that to the size that we want // now scale that to the size that we want
var realScale = horizontal ? ((double)info.Height / info.Width) : ((double)info.Width / info.Height); var realScale = horizontal ? ((double)info.Height / info.Width) : ((double)info.Width / info.Height);
SKImageInfo desired; SKImageInfo desired;
if (horizontal) if (horizontal)
{ {
desired = new SKImageInfo(decodeSize, (int)(realScale * decodeSize)); desired = new SKImageInfo(decodeSize, (int)(realScale * decodeSize));
} }
else else
{ {
desired = new SKImageInfo((int)(realScale * decodeSize), decodeSize); desired = new SKImageInfo((int)(realScale * decodeSize), decodeSize);
} }
if (bmp.Width != desired.Width || bmp.Height != desired.Height) if (bmp.Width != desired.Width || bmp.Height != desired.Height)
{
if (bmp.Height != bmp.Width)
{ {
if (bmp.Height != bmp.Width)
{
}
var scaledBmp = bmp.Resize(desired, interpolationMode.ToSKFilterQuality());
bmp.Dispose();
bmp = scaledBmp;
} }
var scaledBmp = bmp.Resize(desired, interpolationMode.ToSKFilterQuality());
bmp.Dispose();
bmp = scaledBmp;
}
_image = SKImage.FromBitmap(bmp); _image = SKImage.FromBitmap(bmp);
bmp.Dispose(); bmp.Dispose();
if (_image == null) if (_image == null)
{ {
throw new ArgumentException("Unable to load bitmap from provided data"); throw new ArgumentException("Unable to load bitmap from provided data");
} }
PixelSize = new PixelSize(_image.Width, _image.Height); PixelSize = new PixelSize(_image.Width, _image.Height);
// TODO: Skia doesn't have an API for DPI. // TODO: Skia doesn't have an API for DPI.
Dpi = new Vector(96, 96); Dpi = new Vector(96, 96);
}
} }
/// <summary> /// <summary>

Loading…
Cancel
Save