فهرست منبع

Initial implementation of BitmapScaleMode

Benedikt Schroeder 7 سال پیش
والد
کامیت
b108ffcab4

+ 1 - 0
.gitignore

@@ -182,3 +182,4 @@ project.lock.json
 ## BenchmarkDotNet
 ##################
 BenchmarkDotNet.Artifacts/
+/src/ImageInterpRepro

+ 42 - 0
Avalonia.sln

@@ -187,6 +187,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Designer.HostApp.N
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia.UnitTests", "tests\Avalonia.Skia.UnitTests\Avalonia.Skia.UnitTests.csproj", "{E1240B49-7B4B-4371-A00E-068778C5CF0B}"
 EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageInterpRepro", "src\ImageInterpRepro\ImageInterpRepro.csproj", "{54A1062E-126E-4813-98A7-8DB9D949CD93}"
+EndProject
 Global
 	GlobalSection(SharedMSBuildProjectFiles) = preSolution
 		src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
@@ -2514,6 +2516,46 @@ Global
 		{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|NetCoreOnly.Build.0 = Release|Any CPU
 		{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|x86.ActiveCfg = Release|Any CPU
 		{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|x86.Build.0 = Release|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Ad-Hoc|NetCoreOnly.ActiveCfg = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Ad-Hoc|NetCoreOnly.Build.0 = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.AppStore|iPhone.Build.0 = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.AppStore|NetCoreOnly.ActiveCfg = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.AppStore|NetCoreOnly.Build.0 = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.AppStore|x86.ActiveCfg = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.AppStore|x86.Build.0 = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Debug|NetCoreOnly.ActiveCfg = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Debug|NetCoreOnly.Build.0 = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Debug|x86.Build.0 = Debug|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Release|Any CPU.Build.0 = Release|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Release|iPhone.Build.0 = Release|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Release|NetCoreOnly.ActiveCfg = Release|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Release|NetCoreOnly.Build.0 = Release|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Release|x86.ActiveCfg = Release|Any CPU
+		{54A1062E-126E-4813-98A7-8DB9D949CD93}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 17 - 2
src/Avalonia.Controls/Image.cs

@@ -7,6 +7,8 @@ using Avalonia.Media.Imaging;
 
 namespace Avalonia.Controls
 {
+    using Avalonia.Visuals.Media.Imaging;
+
     /// <summary>
     /// Displays a <see cref="Bitmap"/> image.
     /// </summary>
@@ -24,10 +26,17 @@ namespace Avalonia.Controls
         public static readonly StyledProperty<Stretch> StretchProperty =
             AvaloniaProperty.Register<Image, Stretch>(nameof(Stretch), Stretch.Uniform);
 
+        /// <summary>
+        /// Defines the <see cref="ScalingMode"/> property.
+        /// </summary>
+        public static readonly StyledProperty<BitmapScalingMode> ScalingModeProperty =
+            AvaloniaProperty.Register<Image, BitmapScalingMode>(nameof(BitmapScalingMode));
+
         static Image()
         {
             AffectsRender(SourceProperty);
             AffectsRender(StretchProperty);
+            AffectsRender(ScalingModeProperty);
         }
 
         /// <summary>
@@ -48,6 +57,12 @@ namespace Avalonia.Controls
             set { SetValue(StretchProperty, value); }
         }
 
+        public BitmapScalingMode ScalingMode
+        {
+            get { return (BitmapScalingMode)GetValue(ScalingModeProperty); }
+            set { SetValue(ScalingModeProperty, value); }
+        }
+
         /// <summary>
         /// Renders the control.
         /// </summary>
@@ -68,7 +83,7 @@ namespace Avalonia.Controls
                 Rect sourceRect = new Rect(sourceSize)
                     .CenterRect(new Rect(destRect.Size / scale));
 
-                context.DrawImage(source, 1, sourceRect, destRect);
+                context.DrawImage(source, 1, sourceRect, destRect, ScalingMode);
             }
         }
 
@@ -100,4 +115,4 @@ namespace Avalonia.Controls
             }
         }
     }
-}
+}

+ 6 - 3
src/Avalonia.Visuals/Media/DrawingContext.cs

@@ -5,6 +5,8 @@ using Avalonia.Platform;
 
 namespace Avalonia.Media
 {
+    using Avalonia.Visuals.Media.Imaging;
+
     public sealed class DrawingContext : IDisposable
     {
         private int _currentLevel;
@@ -68,11 +70,12 @@ namespace Avalonia.Media
         /// <param name="opacity">The opacity to draw with.</param>
         /// <param name="sourceRect">The rect in the image to draw.</param>
         /// <param name="destRect">The rect in the output to draw to.</param>
-        public void DrawImage(IBitmap source, double opacity, Rect sourceRect, Rect destRect)
+        /// <param name="scalingMode"></param>
+        public void DrawImage(IBitmap source, double opacity, Rect sourceRect, Rect destRect, BitmapScalingMode scalingMode = default)
         {
             Contract.Requires<ArgumentNullException>(source != null);
 
-            PlatformImpl.DrawImage(source.PlatformImpl, opacity, sourceRect, destRect);
+            PlatformImpl.DrawImage(source.PlatformImpl, opacity, sourceRect, destRect, scalingMode);
         }
 
         /// <summary>
@@ -309,4 +312,4 @@ namespace Avalonia.Media
             return pen?.Brush != null && pen.Thickness > 0;
         }
     }
-}
+}

+ 1 - 1
src/Avalonia.Visuals/Platform/IDrawingContextImpl.cs

@@ -33,7 +33,7 @@ namespace Avalonia.Platform
         /// <param name="sourceRect">The rect in the image to draw.</param>
         /// <param name="destRect">The rect in the output to draw to.</param>
         /// <param name="scalingMode">Controls</param>
-        void DrawImage(IRef<IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect, BitmapScalingMode scalingMode = BitmapScalingMode.LowQuality);
+        void DrawImage(IRef<IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect, BitmapScalingMode scalingMode = default);
 
         /// <summary>
         /// Draws a bitmap image.

+ 27 - 5
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@@ -14,6 +14,8 @@ using SkiaSharp;
 
 namespace Avalonia.Skia
 {
+    using Avalonia.Visuals.Media.Imaging;
+
     /// <summary>
     /// Skia based drawing context.
     /// </summary>
@@ -95,24 +97,44 @@ namespace Avalonia.Skia
         }
 
         /// <inheritdoc />
-        public void DrawImage(IRef<IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect)
+        public void DrawImage(IRef<IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect, BitmapScalingMode scalingMode)
         {
-            var drawableImage = (IDrawableBitmapImpl) source.Item;
+            var drawableImage = (IDrawableBitmapImpl)source.Item;
             var s = sourceRect.ToSKRect();
             var d = destRect.ToSKRect();
 
             using (var paint =
-                new SKPaint {Color = new SKColor(255, 255, 255, (byte) (255 * opacity * _currentOpacity))})
+                new SKPaint
+                {
+                    Color = new SKColor(255, 255, 255, (byte)(255 * opacity * _currentOpacity))
+                })
             {
+                paint.FilterQuality = GetInterpolationMode(scalingMode);
+
                 drawableImage.Draw(this, s, d, paint);
             }
         }
 
+        private static SKFilterQuality GetInterpolationMode(BitmapScalingMode scalingMode)
+        {
+            switch (scalingMode)
+            {
+                case BitmapScalingMode.LowQuality:
+                    return SKFilterQuality.Low;
+                case BitmapScalingMode.MediumQuality:
+                    return SKFilterQuality.Medium;
+                case BitmapScalingMode.HighQuality:
+                    return SKFilterQuality.High;
+                default:
+                    throw new ArgumentOutOfRangeException(nameof(scalingMode), scalingMode, null);
+            }
+        }
+
         /// <inheritdoc />
         public void DrawImage(IRef<IBitmapImpl> source, IBrush opacityMask, Rect opacityMaskRect, Rect destRect)
         {
             PushOpacityMask(opacityMask, opacityMaskRect);
-            DrawImage(source, 1, new Rect(0, 0, source.Item.PixelWidth, source.Item.PixelHeight), destRect);
+            DrawImage(source, 1, new Rect(0, 0, source.Item.PixelWidth, source.Item.PixelHeight), destRect, default(BitmapScalingMode));
             PopOpacityMask();
         }
 
@@ -686,4 +708,4 @@ namespace Avalonia.Skia
             }
         }
     }
-}
+}