diff --git a/src/Avalonia.Base/Media/Imaging/Bitmap.cs b/src/Avalonia.Base/Media/Imaging/Bitmap.cs index cf8a31c3e9..ce38fc5abc 100644 --- a/src/Avalonia.Base/Media/Imaging/Bitmap.cs +++ b/src/Avalonia.Base/Media/Imaging/Bitmap.cs @@ -121,18 +121,28 @@ namespace Avalonia.Media.Imaging /// Saves the bitmap to a file. /// /// The filename. - public void Save(string fileName) + /// + /// The optional quality for compression. + /// The quality value is interpreted from 0 - 100. If quality is null the default quality + /// setting is applied. + /// + public void Save(string fileName, int? quality = null) { - PlatformImpl.Item.Save(fileName); + PlatformImpl.Item.Save(fileName, quality); } /// /// Saves the bitmap to a stream. /// /// The stream. - public void Save(Stream stream) + /// + /// The optional quality for compression. + /// The quality value is interpreted from 0 - 100. If quality is null the default quality + /// setting is applied. + /// + public void Save(Stream stream, int? quality = null) { - PlatformImpl.Item.Save(stream); + PlatformImpl.Item.Save(stream, quality); } /// diff --git a/src/Avalonia.Base/Media/Imaging/IBitmap.cs b/src/Avalonia.Base/Media/Imaging/IBitmap.cs index bd04d5ce86..e7d1862aa2 100644 --- a/src/Avalonia.Base/Media/Imaging/IBitmap.cs +++ b/src/Avalonia.Base/Media/Imaging/IBitmap.cs @@ -35,12 +35,22 @@ namespace Avalonia.Media.Imaging /// Saves the bitmap to a file. /// /// The filename. - void Save(string fileName); + /// + /// The optional quality for compression if supported by the specific backend. + /// The quality value is interpreted from 0 - 100. If quality is null the default quality + /// setting of the backend is applied. + /// + void Save(string fileName, int? quality = null); /// /// Saves the bitmap to a stream in png format. /// /// The stream. - void Save(Stream stream); + /// + /// The optional quality for compression if supported by the specific backend. + /// The quality value is interpreted from 0 - 100. If quality is null the default quality + /// setting of the backend is applied. + /// + void Save(Stream stream, int? quality = null); } } diff --git a/src/Avalonia.Base/Platform/IBitmapImpl.cs b/src/Avalonia.Base/Platform/IBitmapImpl.cs index 8f11f68e7c..299a758961 100644 --- a/src/Avalonia.Base/Platform/IBitmapImpl.cs +++ b/src/Avalonia.Base/Platform/IBitmapImpl.cs @@ -29,12 +29,22 @@ namespace Avalonia.Platform /// Saves the bitmap to a file. /// /// The filename. - void Save(string fileName); + /// + /// The optional quality for compression if supported by the specific backend. + /// The quality value is interpreted from 0 - 100. If quality is null the default quality + /// setting of the backend is applied. + /// + void Save(string fileName, int? quality = null); /// /// Saves the bitmap to a stream in png format. /// /// The stream. - void Save(Stream stream); + /// + /// The optional quality for compression if supported by the specific backend. + /// The quality value is interpreted from 0 - 100. If quality is null the default quality + /// setting of the backend is applied. + /// + void Save(Stream stream, int? quality = null); } } diff --git a/src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs b/src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs index 501d239cee..7abc0ca131 100644 --- a/src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs +++ b/src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs @@ -323,12 +323,12 @@ namespace Avalonia.Headless public Vector Dpi { get; } public PixelSize PixelSize { get; } public int Version { get; set; } - public void Save(string fileName) + public void Save(string fileName, int? quality = null) { } - public void Save(Stream stream) + public void Save(Stream stream, int? quality = null) { } diff --git a/src/Skia/Avalonia.Skia/Gpu/OpenGl/OpenGlBitmapImpl.cs b/src/Skia/Avalonia.Skia/Gpu/OpenGl/OpenGlBitmapImpl.cs index d700d4848e..857433f95f 100644 --- a/src/Skia/Avalonia.Skia/Gpu/OpenGl/OpenGlBitmapImpl.cs +++ b/src/Skia/Avalonia.Skia/Gpu/OpenGl/OpenGlBitmapImpl.cs @@ -25,9 +25,9 @@ namespace Avalonia.Skia public Vector Dpi { get; } public PixelSize PixelSize { get; } public int Version { get; private set; } - public void Save(string fileName) => throw new NotSupportedException(); + public void Save(string fileName, int? quality = null) => throw new NotSupportedException(); - public void Save(Stream stream) => throw new NotSupportedException(); + public void Save(Stream stream, int? quality = null) => throw new NotSupportedException(); public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKPaint paint) { diff --git a/src/Skia/Avalonia.Skia/Helpers/ImageSavingHelper.cs b/src/Skia/Avalonia.Skia/Helpers/ImageSavingHelper.cs index 5fa961cc99..b4dd754822 100644 --- a/src/Skia/Avalonia.Skia/Helpers/ImageSavingHelper.cs +++ b/src/Skia/Avalonia.Skia/Helpers/ImageSavingHelper.cs @@ -14,14 +14,19 @@ namespace Avalonia.Skia.Helpers /// /// Image to save /// Target file. - public static void SaveImage(SKImage image, string fileName) + /// + /// The optional quality for PNG compression. + /// The quality value is interpreted from 0 - 100. If quality is null + /// the encoder applies the default quality value. + /// + public static void SaveImage(SKImage image, string fileName, int? quality = null) { if (image == null) throw new ArgumentNullException(nameof(image)); if (fileName == null) throw new ArgumentNullException(nameof(fileName)); using (var stream = File.Create(fileName)) { - SaveImage(image, stream); + SaveImage(image, stream, quality); } } @@ -29,16 +34,30 @@ namespace Avalonia.Skia.Helpers /// Save Skia image to a stream. /// /// Image to save - /// Target stream. - public static void SaveImage(SKImage image, Stream stream) + /// + /// The optional quality for PNG compression. + /// The quality value is interpreted from 0 - 100. If quality is null + /// the encoder applies the default quality value. + /// + public static void SaveImage(SKImage image, Stream stream, int? quality = null) { if (image == null) throw new ArgumentNullException(nameof(image)); if (stream == null) throw new ArgumentNullException(nameof(stream)); - using (var data = image.Encode()) + if (quality == null) { - data.SaveTo(stream); + using (var data = image.Encode()) + { + data.SaveTo(stream); + } + } + else + { + using (var data = image.Encode(SKEncodedImageFormat.Png, (int)quality)) + { + data.SaveTo(stream); + } } } } -} \ No newline at end of file +} diff --git a/src/Skia/Avalonia.Skia/ImmutableBitmap.cs b/src/Skia/Avalonia.Skia/ImmutableBitmap.cs index 6400d67fde..e24d805050 100644 --- a/src/Skia/Avalonia.Skia/ImmutableBitmap.cs +++ b/src/Skia/Avalonia.Skia/ImmutableBitmap.cs @@ -139,13 +139,13 @@ namespace Avalonia.Skia } /// - public void Save(string fileName) + public void Save(string fileName, int? quality = null) { ImageSavingHelper.SaveImage(_image, fileName); } /// - public void Save(Stream stream) + public void Save(Stream stream, int? quality = null) { ImageSavingHelper.SaveImage(_image, stream); } diff --git a/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs b/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs index 01b7449b64..d3231c92a5 100644 --- a/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs +++ b/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs @@ -116,20 +116,20 @@ namespace Avalonia.Skia public int Version { get; private set; } = 1; /// - public void Save(string fileName) + public void Save(string fileName, int? quality = null) { using (var image = SnapshotImage()) { - ImageSavingHelper.SaveImage(image, fileName); + ImageSavingHelper.SaveImage(image, fileName, quality); } } /// - public void Save(Stream stream) + public void Save(Stream stream, int? quality = null) { using (var image = SnapshotImage()) { - ImageSavingHelper.SaveImage(image, stream); + ImageSavingHelper.SaveImage(image, stream, quality); } } diff --git a/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs b/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs index 80bfcc5973..d437f514bb 100644 --- a/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs +++ b/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs @@ -137,20 +137,20 @@ namespace Avalonia.Skia } /// - public void Save(Stream stream) + public void Save(Stream stream, int? quality = null) { using (var image = GetSnapshot()) { - ImageSavingHelper.SaveImage(image, stream); + ImageSavingHelper.SaveImage(image, stream, quality); } } /// - public void Save(string fileName) + public void Save(string fileName, int? quality = null) { using (var image = GetSnapshot()) { - ImageSavingHelper.SaveImage(image, fileName); + ImageSavingHelper.SaveImage(image, fileName, quality); } } diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs index 843efe2cc4..059105c112 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs @@ -15,7 +15,7 @@ namespace Avalonia.Direct2D1.Media public abstract OptionalDispose GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget target); - public void Save(string fileName) + public void Save(string fileName, int? quality = null) { if (Path.GetExtension(fileName) != ".png") { @@ -25,11 +25,11 @@ namespace Avalonia.Direct2D1.Media using (FileStream s = new FileStream(fileName, FileMode.Create)) { - Save(s); + Save(s, quality); } } - public abstract void Save(Stream stream); + public abstract void Save(Stream stream, int? quality = null); public virtual void Dispose() { diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DBitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DBitmapImpl.cs index 2656ab4c58..a321b225a0 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DBitmapImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DBitmapImpl.cs @@ -43,7 +43,7 @@ namespace Avalonia.Direct2D1.Media return new OptionalDispose(_direct2DBitmap, false); } - public override void Save(Stream stream) + public override void Save(Stream stream, int? quality = null) { using (var encoder = new PngBitmapEncoder(Direct2D1Platform.ImagingFactory, stream)) using (var frame = new BitmapFrameEncode(encoder)) diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs index 357e472d34..c5f8e837ce 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs @@ -56,7 +56,7 @@ namespace Avalonia.Direct2D1.Media.Imaging return new OptionalDispose(_renderTarget.Bitmap, false); } - public override void Save(Stream stream) + public override void Save(Stream stream, int? quality = null) { using (var wic = new WicRenderTargetBitmapImpl(PixelSize, Dpi)) { diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs index 1156246b29..051790ef03 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs @@ -186,7 +186,7 @@ namespace Avalonia.Direct2D1.Media return new OptionalDispose(D2DBitmap.FromWicBitmap(renderTarget, converter), true); } - public override void Save(Stream stream) + public override void Save(Stream stream, int? quality = null) { using (var encoder = new PngBitmapEncoder(Direct2D1Platform.ImagingFactory, stream)) using (var frame = new BitmapFrameEncode(encoder))