From b4196f86bb6a4790bf697d03649f90555132a36e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Feb 2026 21:50:10 +0000 Subject: [PATCH 1/4] Initial plan From 2a344a98c22aafc2bb346e4719922dea475af642 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Feb 2026 22:03:21 +0000 Subject: [PATCH 2/4] Update SkiaSharp from 2.88.8 to 3.119.2 and fix breaking API changes Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --- eng/Versions.props | 2 +- src/Microsoft.ML.ImageAnalytics/MLImage.cs | 13 +++++-------- .../Microsoft.ML.ImageAnalytics.csproj | 2 ++ 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index fb2e1d31c6..1525ac693c 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -19,7 +19,7 @@ 9.0.4 9.0.4 6.9.1 - 2.88.8 + 3.119.2 9.0.4 9.0.4 9.0.4 diff --git a/src/Microsoft.ML.ImageAnalytics/MLImage.cs b/src/Microsoft.ML.ImageAnalytics/MLImage.cs index 4bb3a0571d..b8251e32b5 100644 --- a/src/Microsoft.ML.ImageAnalytics/MLImage.cs +++ b/src/Microsoft.ML.ImageAnalytics/MLImage.cs @@ -155,14 +155,14 @@ public byte[] GetBGRPixels /// /// Gets the image pixel data. /// - public ReadOnlySpan Pixels + public unsafe ReadOnlySpan Pixels { get { ThrowInvalidOperationExceptionIfDisposed(); Debug.Assert(_image.Info.BytesPerPixel == 4); - return _image.GetPixelSpan(); + return new ReadOnlySpan(_image.GetPixels().ToPointer(), _image.ByteCount); } } @@ -305,7 +305,7 @@ internal MLImage CloneWithResizing(int width, int height, ImageResizeMode mode) return new MLImage(image); } - private SKBitmap ResizeFull(int width, int height) => _image.Resize(new SKSizeI(width, height), SKFilterQuality.None); + private SKBitmap ResizeFull(int width, int height) => _image.Resize(new SKSizeI(width, height), new SKSamplingOptions(SKFilterMode.Nearest)); private SKBitmap ResizeWithPadding(int width, int height) { @@ -334,9 +334,8 @@ private SKBitmap ResizeWithPadding(int width, int height) SKRect destRect = new SKRect(destX, destY, destX + destWidth, destY + destHeight); using SKCanvas canvas = new SKCanvas(destBitmap); - using SKPaint paint = new SKPaint() { FilterQuality = SKFilterQuality.High }; - canvas.DrawBitmap(_image, srcRect, destRect, paint); + canvas.DrawBitmap(_image, srcRect, destRect); return destBitmap; } @@ -391,9 +390,8 @@ private SKBitmap ResizeWithCrop(int width, int height, ImageResizeMode mode) SKRect destRect = new SKRect(destX, destY, destX + destWidth, destY + destHeight); using SKCanvas canvas = new SKCanvas(dst); - using SKPaint paint = new SKPaint() { FilterQuality = SKFilterQuality.High }; - canvas.DrawBitmap(_image, srcRect, destRect, paint); + canvas.DrawBitmap(_image, srcRect, destRect); return dst; } @@ -415,7 +413,6 @@ internal MLImage CloneWithGrayscale() using SKPaint paint = new SKPaint() { ColorFilter = _grayscaleColorMatrix, - FilterQuality = SKFilterQuality.High }; SKBitmap destBitmap = new SKBitmap(_image.Width, _image.Height, isOpaque: true); diff --git a/src/Microsoft.ML.ImageAnalytics/Microsoft.ML.ImageAnalytics.csproj b/src/Microsoft.ML.ImageAnalytics/Microsoft.ML.ImageAnalytics.csproj index 4f4213309b..434aa4c882 100644 --- a/src/Microsoft.ML.ImageAnalytics/Microsoft.ML.ImageAnalytics.csproj +++ b/src/Microsoft.ML.ImageAnalytics/Microsoft.ML.ImageAnalytics.csproj @@ -11,6 +11,8 @@ + + From 0d13f3b8bd8f7dd7fbb6868ae139962783ec4bbc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Feb 2026 22:05:18 +0000 Subject: [PATCH 3/4] Use high-quality SKCubicResampler.Mitchell for resize operations Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --- src/Microsoft.ML.ImageAnalytics/MLImage.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.ML.ImageAnalytics/MLImage.cs b/src/Microsoft.ML.ImageAnalytics/MLImage.cs index b8251e32b5..b8337e3d20 100644 --- a/src/Microsoft.ML.ImageAnalytics/MLImage.cs +++ b/src/Microsoft.ML.ImageAnalytics/MLImage.cs @@ -334,8 +334,9 @@ private SKBitmap ResizeWithPadding(int width, int height) SKRect destRect = new SKRect(destX, destY, destX + destWidth, destY + destHeight); using SKCanvas canvas = new SKCanvas(destBitmap); + using SKImage image = SKImage.FromBitmap(_image); - canvas.DrawBitmap(_image, srcRect, destRect); + canvas.DrawImage(image, srcRect, destRect, new SKSamplingOptions(SKCubicResampler.Mitchell)); return destBitmap; } @@ -390,8 +391,9 @@ private SKBitmap ResizeWithCrop(int width, int height, ImageResizeMode mode) SKRect destRect = new SKRect(destX, destY, destX + destWidth, destY + destHeight); using SKCanvas canvas = new SKCanvas(dst); + using SKImage image = SKImage.FromBitmap(_image); - canvas.DrawBitmap(_image, srcRect, destRect); + canvas.DrawImage(image, srcRect, destRect, new SKSamplingOptions(SKCubicResampler.Mitchell)); return dst; } From 00d95ab29f5ac34202f29562dcc857147d2fd235 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Feb 2026 03:21:47 +0000 Subject: [PATCH 4/4] Address review feedback: fix csproj comment and add pixel pointer validation Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --- src/Microsoft.ML.ImageAnalytics/MLImage.cs | 6 +++++- .../Microsoft.ML.ImageAnalytics.csproj | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.ML.ImageAnalytics/MLImage.cs b/src/Microsoft.ML.ImageAnalytics/MLImage.cs index b8337e3d20..15ab01439e 100644 --- a/src/Microsoft.ML.ImageAnalytics/MLImage.cs +++ b/src/Microsoft.ML.ImageAnalytics/MLImage.cs @@ -162,7 +162,11 @@ public unsafe ReadOnlySpan Pixels ThrowInvalidOperationExceptionIfDisposed(); Debug.Assert(_image.Info.BytesPerPixel == 4); - return new ReadOnlySpan(_image.GetPixels().ToPointer(), _image.ByteCount); + var pixelsPtr = _image.GetPixels(); + if (pixelsPtr == IntPtr.Zero || _image.ByteCount <= 0) + throw new InvalidOperationException("Pixel data is unavailable."); + + return new ReadOnlySpan(pixelsPtr.ToPointer(), _image.ByteCount); } } diff --git a/src/Microsoft.ML.ImageAnalytics/Microsoft.ML.ImageAnalytics.csproj b/src/Microsoft.ML.ImageAnalytics/Microsoft.ML.ImageAnalytics.csproj index 434aa4c882..158287c158 100644 --- a/src/Microsoft.ML.ImageAnalytics/Microsoft.ML.ImageAnalytics.csproj +++ b/src/Microsoft.ML.ImageAnalytics/Microsoft.ML.ImageAnalytics.csproj @@ -13,7 +13,7 @@ - +