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 @@
-
+