Skip to content

Migrate imaging from ImageSharp to SkiaSharp + add exhaustive Skia-based tests#150

Merged
stesee merged 3 commits into
Codeuctivity:mainfrom
mapo80:main
Aug 15, 2025
Merged

Migrate imaging from ImageSharp to SkiaSharp + add exhaustive Skia-based tests#150
stesee merged 3 commits into
Codeuctivity:mainfrom
mapo80:main

Conversation

@mapo80

@mapo80 mapo80 commented Aug 15, 2025

Copy link
Copy Markdown

Migrate imaging from ImageSharp to SkiaSharp + add exhaustive Skia-based tests

Summary

This PR replaces SixLabors.ImageSharp with SkiaSharp for image decoding/encoding and color handling across the codebase, and adds a comprehensive test suite to validate the new behavior. It also updates documentation to reflect the migration and adds build/test instructions. ([GitHub][1])

Why

  • Licensing & adoption: ImageSharp’s licensing can require commercial agreements in some scenarios. SkiaSharp (MIT) reduces licensing friction while keeping rich imaging capabilities. The README now documents this rationale under “SkiaSharp migration.” ([GitHub][2])
  • Cross-platform stability: SkiaSharp provides mature, cross-platform bindings to Google’s Skia engine. Native asset packages are included to ensure CI/Linux compatibility. ([GitHub][2])

What changed

Library code

  • Color handling

    • ColorParser now uses SkiaSharp.SKColor and System.Drawing.ColorTranslator to parse named/hex colors.

    • Signatures changed:

      • ColorParser.FromName(string) → returns SKColor
      • ColorParser.TryFromName(string?, out SKColor)
        This replaces prior ImageSharp types and parsing. ([GitHub][1])
  • HTML → WML image processing

    • Rewrote image transformation logic to decode via SKBitmap and encode via SKImage.Encode (PNG/JPEG/WebP), including handling of data-URI sources.
    • Fix: write image bytes using ba.Length (instead of GetUpperBound(0)+1). ([GitHub][1])
  • Project references

    • Removed ImageSharp; added:

      • SkiaSharp 3.119.0
      • SkiaSharp.NativeAssets.Linux.NoDependencies 3.119.0 (both library and test project)
    • Kept SixLabors.Fonts as before. ([GitHub][2])

Tests

Added an exhaustive suite validating color parsing, CSS color coercion, and image transform behaviors:

  • ColorParserTests — case-insensitive named colors, hex variants (#RRGGBB, #RGB), invalid inputs, and exception behavior. ([GitHub][2])
  • CssPropertyValueTests — verifies detection and conversion of color-like CSS values into SKColor. ([GitHub][2])
  • ImageHandlerTests — ensures generated data: URIs with correct MIME type (PNG/JPEG/WEBP/GIF), alt text behavior, and error conditions on invalid bytes. ([GitHub][2])

Docs

  • README: new “SkiaSharp migration” section explaining rationale and impact. ([GitHub][2])
  • AGENTS.md: quick build/test instructions (dotnet build, dotnet test) for contributors. ([GitHub][1])

Backward compatibility

  • Breaking change: ColorParser returns SkiaSharp.SKColor instead of the previous ImageSharp color type.
    If downstream code relied on the old type, conversion helpers are straightforward (e.g., map SKColor to System.Drawing.Color with channel copy). Consider accepting this change now to remove the ImageSharp dependency; if needed, I can add temporary shim methods returning System.Drawing.Color to ease migration. ([GitHub][1])

  • Runtime: SkiaSharp introduces native dependencies on Linux; the PR includes SkiaSharp.NativeAssets.Linux.NoDependencies in both library and tests so CI/Linux builds run out of the box. ([GitHub][2])


How to test

dotnet restore
dotnet build
dotnet test

All new tests are deterministic and run cross-platform. See OpenXmlPowerTools.Tests/* for coverage of colors, CSS parsing, and image transformation. ([GitHub][2])


Implementation notes

  • Image decoding: SKBitmap.Decode(...) for file paths and base64 data URIs; encode via SKImage.Encode(...) (PNG default) before adding to the OpenXML package. ([GitHub][1])
  • Color parsing: ColorTranslator.FromHtml(...) leveraged for named/hex inputs; strict validation via TryFromName. ([GitHub][1])

Related work

This fork tracks the active Codeuctivity/OpenXmlPowerTools lineage; releases continue to be published there. This PR targets that repo to consolidate the SkiaSharp migration and its tests upstream. ([GitHub][3])


Checklist

  • Replace ImageSharp usage with SkiaSharp
  • Add native assets for Linux to lib & tests
  • Add comprehensive unit tests for color/CSS/image transforms
  • Update README with migration notes
  • Add contributor build/test instructions

Copilot AI review requested due to automatic review settings August 15, 2025 15:22
@mapo80 mapo80 requested a review from stesee as a code owner August 15, 2025 15:22
@github-actions

github-actions Bot commented Aug 15, 2025

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR migrates the imaging library from ImageSharp to SkiaSharp for license compatibility and cross-platform stability. The change replaces ImageSharp's commercial licensing model with SkiaSharp's permissive MIT license while maintaining rich imaging capabilities through Skia's graphics engine.

  • Replace ImageSharp with SkiaSharp for image decoding/encoding and color handling
  • Add comprehensive test suite covering color parsing, CSS conversion, and image transformations
  • Update documentation with migration rationale and build instructions

Reviewed Changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
README.md Documents SkiaSharp migration rationale and benefits
OpenXmlPowerTools.csproj Replaces ImageSharp package with SkiaSharp and native Linux assets
ColorParser.cs Migrates from ImageSharp Color to SKColor with System.Drawing.ColorTranslator
OxPtHelpers.cs Updates color handling to use SKColor properties and hex formatting
HtmlToWmlCssParser.cs Converts CSS color parsing from ImageSharp to SkiaSharp types
HtmlToWmlConverterCore.cs Replaces image processing with SkiaSharp bitmap/codec APIs
ImageHandler.cs Rewrites image transformation using SKCodec and MIME type detection
Test files Adds comprehensive test coverage for new SkiaSharp-based functionality
AGENTS.md Provides build and test instructions for contributors

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

using (var s = newPart.GetStream(FileMode.Create, FileAccess.ReadWrite))
{
s.Write(ba, 0, ba.GetUpperBound(0) + 1);
s.Write(ba, 0, ba.Length);

Copilot AI Aug 15, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bug fix correctly changes from ba.GetUpperBound(0) + 1 to ba.Length. However, the old code should have been s.Write(ba, 0, ba.GetUpperBound(0) + 1); but the diff shows it was s.Write(ba, 0, ba.GetUpperBound(0) + 1);. This suggests the original code may have been incorrect for multi-dimensional arrays, but since ba is a byte array (single dimension), GetUpperBound(0) + 1 equals Length. The fix is correct but the original issue description may be misleading.

Copilot uses AI. Check for mistakes.
{
SixLabors.ImageSharp.Color colorValue;
SkiaSharp.SKColor colorValue;
if (!ColorParser.TryFromName(backColor, out colorValue))

Copilot AI Aug 15, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable name is inconsistent - the method checks backColor but the error message references foreColor. This should check foreColor since that's the variable being validated for the foreground color.

Suggested change
if (!ColorParser.TryFromName(backColor, out colorValue))
if (!ColorParser.TryFromName(foreColor, out colorValue))

Copilot uses AI. Check for mistakes.
@mapo80

mapo80 commented Aug 15, 2025

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

github-actions Bot added a commit that referenced this pull request Aug 15, 2025
@stesee stesee merged commit 2588592 into Codeuctivity:main Aug 15, 2025
6 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 15, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants