Skip to content

Releases: guitarrapc/SkiaSharp.QrCode

0.12.0

28 Nov 14:27
39e6356

Choose a tag to compare

Overview

fix: remove gray borders around QR code modules by disabling antialiasing.

Fixed: Gray Borders Around QR Code Modules

Previous versions displayed unwanted gray borders around rectangular QR code modules when antialiasing was enabled. This occurred because antialiasing creates semi-transparent pixels at edges, which blend with the background to create visible gray lines between modules.

Solution:

  • Introduced shape-specific antialiasing control via ModuleShape.RequiresAntialiasing property
  • Rectangular modules now render without antialiasing for crisp, border-free edges
  • Circular and rounded rectangle modules maintain antialiasing for smooth curves
  • Text rendering in icons preserves antialiasing for optimal readability

Before:
Rectangular modules had visible gray borders between them.

image

After:
Sharp, clean module edges with no visual artifacts.

image

What's Changed

  • [dotnet format] Automated changes by @github-actions[bot] in #280
  • fix: remove gray borders around QR code modules by disabling antialiasing by @guitarrapc in #282

Full Changelog: 0.11.0...0.12.0

0.11.0

16 Nov 12:32
b9d4d79

Choose a tag to compare

Overview

This release introduces customizable icon rendering with new IconShape support, enabling you to add both images and text to your QR codes. You can now create QR codes with branded logos accompanied by text labels for enhanced visual appeal.

Also QRCodeImageBuilder now accept QRCodeData directly, enabling you to directly render compress/decompress scenario.


Breaking change

Customizable Icon Rendering

The IconData class now supports flexible icon rendering through the new IconShape abstraction:

  • ImageIconShape - Display images only (replaces direct SKBitmap usage)
  • ImageTextIconShape - Combine images with text labels
  • Future extensibility for custom icon shapes

Breaking Change: IconData.Icon Property

Before (0.10.0 and earlier):

using var bitmap = SKBitmap.Decode(File.ReadAllBytes(iconPath));
var icon = new IconData
{
    Icon = bitmap,  // Direct SKBitmap
    IconSizePercent = 15,
    IconBorderWidth = 10
};

After (0.11.0):

using var bitmap = SKBitmap.Decode(File.ReadAllBytes(iconPath));

// Option 1: Quick creation with helper method
var icon = IconData.FromImage(bitmap, iconSizePercent: 15, iconBorderWidth: 18);

// Option 2: Image-only icon
var icon = new IconData
{
    Icon = new ImageIconShape(bitmap),
    IconSizePercent = 15,
    IconBorderWidth = 10
};

// Option 3: Image with text label
using var font = new SKFont
{
    Size = 18,
    Typeface = SKTypeface.FromFamilyName("sans-serif", SKFontStyle.Bold)
};
var icon = new IconData
{
    Icon = new ImageTextIconShape(bitmap, "FooBar", SKColors.Black, font, textPadding: 2),
    IconSizePercent = 13,
    IconBorderWidth = 18
};

Enhanced QRCodeData Support

Added QRCodeImageBuilder constructor overload accepting QRCodeData directly, enabling advanced scenarios:

// compression to zstandard ...
var qrCodeData = QRCodeGenerator.CreateQrCode("Hello", ECCLevel.L);
var src = qrCodeData.GetRawData();
var size = qrCodeData.GetRawDataSize();

var maxSize = NativeCompressions.Zstandard.GetMaxCompressedLength(size);
var compressed = new byte[maxSize];
NativeCompressions.Zstandard.Compress(src, compressed, NativeCompressions.ZstandardCompressionOptions.Default);

// decompression from zstandard ...
var decompressed = NativeCompressions.Zstandard.Decompress(compressed);

// render QR code
var qr = new QRCodeData(decompressed, 4);
var pngBytes = QRCodeImageBuilder.GetPngBytes(qr, 512);
File.WriteAllBytes(path, pngBytes);

Migration Guide

If you're using IconData in your code, update the Icon property from SKBitmap to IconShape:

  1. Quick fix: Use IconData.FromImage() helper method
  2. Image only: Wrap with ImageIconShape
  3. Image + Text: Use ImageTextIconShape with font configuration

⚠️ Note: Always use ECCLevel.H when adding icons to ensure QR code readability.


What's Changed

  • feat: Add QRCodeData overload for QRCodeImageBuilder by @guitarrapc in #278
  • [Breaking change] feat: Add Iconshape to handle QR Icon. by @guitarrapc in #279

Full Changelog: 0.10.0...0.11.0

0.10.0

14 Nov 19:37
7d073e9

Choose a tag to compare

Overview

This release adds .NET 10.0 support and introduces customizable Finder Pattern rendering, allowing you to create QR codes with distinctive corner styles while maintaining full scan compatibility.


Custom Finder Pattern Rendering

New WithFinderPatternShape() API enables distinctive corner designs:

  • RectangleFinderPatternShape - Classic rectangular pattern
  • RoundedRectangleFinderPatternShape - Smooth rounded corners
  • CircleFinderPatternShape - Circular corners
  • RoundedRectangleCircleFinderPatternShape - Hybrid style with rounded rectangles and circles

Here's sample QR Code with customize finder pattern by RoundedRectangleCircleFinderPatternShape.

pattern14_instagram_style

Code Example

Create a QR code with rounded finder patterns:

var qrCode = new QRCodeImageBuilder("https://example.com")
    .WithSize(512, 512)
    .WithFinderPatternShape(RoundedRectangleFinderPatternShape.Default)
    .WithColors(codeColor: SKColors.DarkBlue);

What's Changed

  • [dotnet format] Automated changes by @github-actions[bot] in #272
  • chore(deps): bump actions/upload-artifact from 4.6.2 to 5.0.0 by @dependabot[bot] in #274
  • chore(deps): bump actions/download-artifact from 5.0.0 to 6.0.0 by @dependabot[bot] in #273
  • feat: add .NET 10 support by @guitarrapc in #275
  • feat: Add cusomize FinderPattern rendering with your defined shape. by @guitarrapc in #276
  • feat: show gradient and medium size of styled QR on BlazorWasm QR page by @guitarrapc in #277

Full Changelog: 0.9.0...0.10.0

0.9.0

25 Oct 08:54
7a749a6

Choose a tag to compare

🎉 Overview

v0.9.0 is a major update that includes significant performance improvements, API redesign, and the introduction of a more user-friendly Builder pattern.


⚡ Performance Improvements

This release dramatically improves QR code generation speed and memory efficiency:

image

Performance for several data types.

image

Memory Allocation Reduction

  • Redesigned QRCodeData implementation from List<BitArray> to 1D byte[] array (#233, #186)
  • Used stackalloc for small datasets to reduce allocations (#236, #209, #212)
  • Leveraged ArrayPool for large datasets (#228, #237)
  • Reused temporary QRCode objects during mask pattern selection (#207, #234)
  • Removed allocations during FinderPattern placement (#243)
  • Reduced re-allocations when adding masks by including QuietZone in constructor (#252)

Algorithm Optimization

  • Replaced LINQ linear search O(n) with lookup table O(1) (#173)
  • Removed LINQ from hot paths (#184, #198, #202)
  • Eliminated Reflection usage (MaskCode) (#191)
  • Executed penalty calculations in a single pass (#231, #241)
  • Optimized Penalty3 calculation with sliding window 11-bit masking (#232)
  • Optimized QR code module placement with bitmask (#244)
  • Pre-calculated mod/div for mask pattern selection (#248)
  • Wrote multiple bits at once (#225)
  • Single-pass text analysis with TextAnalyzer (#229)

Data Structure Improvements

  • Changed QR Code data tables from instance to Lazy static, initializing once (#171)
  • Changed Point & Rectangle from class to readonly record struct (#166)
  • Made Vector2Slim immutable (#196)
  • Changed CodewordBlock to readonly struct (#199)
  • Replaced string format/version operations with uint/ushort (#208)

Other Optimizations

  • Changed char array access to range check for Numeric/AlphaNumeric (#168, #169)
  • Used StringBuilder with capacity (#172)
  • Specified List capacity (#185)
  • Faster ISO-8859-1 validation with range check (#180)
  • Removed unnecessary modulo in Galois multiplication (#247)
  • Removed temporary collections with collection expressions (#211)

💥 Breaking Changes

API Changes

1. QrCode Class Deprecation and Migration to QRCodeImageBuilder

The QrCode class is now obsolete. Please use the new QRCodeImageBuilder instead. See detail #266

Before (Old API):

var qrCode = new QrCode(content, new Vector2Slim(512, 512), SKEncodedImageFormat.Png);
using (var output = new FileStream(path, FileMode.OpenOrCreate))
{
    qrCode.GenerateImage(output);
}

After (New API):

Simple QR code generation with static method:

var pngBytes = QRCodeImageBuilder.GetPngBytes(content);
File.WriteAllBytes(path, pngBytes);

Advanced usage with builder pattern:

using var stream = File.OpenWrite(path);
var pngBytes = new QRCodeImageBuilder(content)
    .WithSize(512, 512)
    .WithErrorCorrection(ECCLevel.H)
    .SaveTo(stream);

Related PRs: #265, #264

2. IDisposable Removal

  • Removed IDisposable from QRCodeData (#214)
  • Removed IDisposable from QRCodeRenderer and changed to static class (#216, #220)

Remove using statements for these classes if you were using them.

// 0.8.0 and before
using var qrCodeData = QRCodeGenerator.CreateQrCode("Hello, World!", ECCLevel.L);

// 0.9.0 and after
var qrCodeData = QRCodeGenerator.CreateQrCode("Hello, World!", ECCLevel.L);
// 0.8.0 and before
using var renderer = new QRCodeRenderer();
renderer.Render(...);

// 0.9.0 and after
QRCodeRenderer.Render(...);

3. Stricter Null Checking

QRCodeRenderer.Render now throws ArgumentNullException when null data is passed (#218)

4. IconData Namespace Move

IconData moved to SkiaSharp.QrCode.Image namespace (#239)

Update your using directives:

using SkiaSharp.QrCode.Image;

5. QuietZone Size Specification

QRCodeData(byte[] rawData) now accepts QuietZoneSize specification (#253)

Removed Features

  • Removed forceUtf8 parameter (#177)
  • Removed ISO-8859-2 encoding support (#178)
  • Removed compression feature (#256)
  • Removed Kanji encoding mode (#269)

Encoding Changes

  • Fixed empty data encoding from Numeric to Byte (#240)

✨ New Features

QRCodeImageBuilder - New Builder Pattern

Introduced a new API that provides static QR code image generation with a fluent builder pattern:

using var image = QRCodeImageBuilder.Create()
    .WithContent("Hello, World!")
    .WithECCLevel(ECCLevel.H)
    .WithSize(pixelsPerModule: 10)
    .WithColors(SKColors.Black, SKColors.White)
    .WithIcon(iconData, iconSizePercent: 15)
    .Build();

Related PR: #264

Enhanced Rendering Features

  • Gradient color support (#263)
  • Enhanced QR code rendering customization options (#261)
  • Consolidated rendering methods and batch rendering (#259, #260)

Binary Data Support

  • Added binary data encoding for QR codes (#204)
  • Changed Binary CreateQrCode to receive ReadOnlySpan<char> (#205)

New APIs

  • Added pre-calculate QR size API (#251)
  • Provided GetRawData(IBufferWriter<byte> writer) API (#257)

🐛 Bug Fixes

  • Fixed invalid QR code generation when upgraded version (EciMode.Default UTF8 fallback) (#179)
  • Fixed ECC encoding to ensure the remainder always produces the expected number of ECC words (#183)
  • Fixed Penalty3 calculation to execute for rows and columns separately (#242)
  • Fixed GetVersion not considering UTF8 BOM header bytes (#250)

🔧 Refactoring & Internal Improvements

Encoding Redesign

  • Replaced QR code generation with QREncoder and ECCEncoder (#176)
  • Pipelined CreateQrCode (#197)
  • **QRCodeGenera...
Read more

0.8.0

30 Sep 19:15
a0c89ed

Choose a tag to compare

This release follow to Upstream SkiaSharp package 3.119.1

What's Changed

  • chore: bump docker sample to use latest package by @guitarrapc in #75
  • chore(deps): bump Microsoft.Fast.Components.FluentUI from 3.4.1 to 3.5.0 by @dependabot[bot] in #77
  • chore(deps): bump xunit from 2.6.3 to 2.6.4 by @dependabot[bot] in #80
  • chore(deps): bump xunit.runner.visualstudio from 2.5.5 to 2.5.6 by @dependabot[bot] in #81
  • chore(deps): bump Microsoft.VisualStudio.Azure.Containers.Tools.Targets from 1.19.5 to 1.19.6 by @dependabot[bot] in #82
  • chore(deps): bump xunit from 2.6.4 to 2.6.5 by @dependabot[bot] in #83
  • chore(deps): bump xunit from 2.6.5 to 2.6.6 by @dependabot[bot] in #84
  • chore(deps): bump Microsoft.AspNetCore.Components.WebAssembly from 8.0.0 to 8.0.1 by @dependabot[bot] in #85
  • chore(deps): bump SkiaSharp.NativeAssets.NanoServer and SkiaSharp by @dependabot[bot] in #86
  • chore(deps): bump SkiaSharp from 2.88.6 to 2.88.7 by @dependabot[bot] in #87
  • chore(deps): bump Microsoft.AspNetCore.Components.WebAssembly.DevServer from 8.0.0 to 8.0.1 by @dependabot[bot] in #88
  • chore(deps): bump Microsoft.Fast.Components.FluentUI from 3.5.0 to 3.5.2 by @dependabot[bot] in #90
  • chore(deps): bump peter-evans/create-pull-request from 5 to 6 by @dependabot[bot] in #94
  • chore(deps): bump Microsoft.AspNetCore.Components.WebAssembly from 8.0.1 to 8.0.2 by @dependabot[bot] in #98
  • ci: bump download-artifact/upload-artifact to v4 by @guitarrapc in #115
  • chore(deps): bump coverlet.collector from 6.0.0 to 6.0.2 by @dependabot[bot] in #103
  • chore(deps): bump SkiaSharp.Views.Blazor and SkiaSharp by @dependabot[bot] in #106
  • chore(deps): bump SkiaSharp.NativeAssets.Linux.NoDependencies and SkiaSharp by @dependabot[bot] in #107
  • ci: docker-compose to docker compose by @guitarrapc in #117
  • chore(deps): bump Microsoft.Fast.Components.FluentUI from 3.5.2 to 3.7.8 by @dependabot[bot] in #114
  • chore(deps): bump Microsoft.NET.Test.Sdk from 17.8.0 to 17.11.0 by @dependabot[bot] in #116
  • chore(deps): bump xunit.runner.visualstudio from 2.5.6 to 2.8.2 by @dependabot[bot] in #124
  • chore(deps): bump Microsoft.AspNetCore.Components.WebAssembly.DevServer from 8.0.1 to 8.0.8 by @dependabot[bot] in #123
  • chore(deps): bump peter-evans/create-pull-request from 6 to 7 by @dependabot[bot] in #119
  • refactor: use full qualified name by @guitarrapc in #125
  • chore(deps): bump xunit from 2.6.6 to 2.9.0 by @dependabot[bot] in #121
  • chore(deps): bump coverlet.msbuild from 6.0.0 to 6.0.2 by @dependabot[bot] in #120
  • chore(deps): bump SkiaSharp.NativeAssets.NanoServer and SkiaSharp by @dependabot[bot] in #122
  • chore(deps): bump Microsoft.AspNetCore.Components.WebAssembly from 8.0.2 to 8.0.10 by @dependabot[bot] in #131
  • chore(deps): bump Microsoft.AspNetCore.Components.WebAssembly.DevServer from 8.0.8 to 8.0.10 by @dependabot[bot] in #133
  • chore(deps): bump Microsoft.NET.Test.Sdk from 17.11.0 to 17.12.0 by @dependabot[bot] in #135
  • chore(deps): bump Microsoft.Fast.Components.FluentUI from 3.7.8 to 3.8.0 by @dependabot[bot] in #136
  • chore(deps): bump Microsoft.VisualStudio.Azure.Containers.Tools.Targets from 1.19.6 to 1.21.0 by @dependabot[bot] in #127
  • chore: drop net 6.7, 7.0 by @guitarrapc in #143
  • ci: pin action sha by @guitarrapc in #142
  • ci: dependabot by @guitarrapc in #144
  • chore(deps): bump GitHubActionsTestLogger from 2.3.3 to 2.4.1 by @dependabot[bot] in #129
  • chore(deps): bump xunit.runner.visualstudio from 2.8.2 to 3.0.2 by @dependabot[bot] in #145
  • chore(deps): bump Microsoft.NET.Test.Sdk from 17.12.0 to 17.13.0 by @dependabot[bot] in #146
  • chore(deps): bump Microsoft.AspNetCore.Components.WebAssembly.DevServer from 8.0.14 to 9.0.3 by @dependabot[bot] in #147
  • chore(deps): bump actions/download-artifact from 4.2.1 to 4.3.0 by @dependabot[bot] in #148
  • chore(deps): bump SkiaSharp.Views.Blazor from 3.116.1 to 3.119.0 by @dependabot[bot] in #153
  • chore(deps): bump xunit.runner.visualstudio from 3.0.2 to 3.1.0 by @dependabot[bot] in #151
  • chore(deps): bump aquaproj/aqua-installer from 3.1.1 to 4.0.0 by @dependabot[bot] in #154
  • chore(deps): bump actions/download-artifact from 4.3.0 to 5.0.0 by @dependabot[bot] in #156
  • chore(deps): bump actions/checkout from 4.2.2 to 5.0.0 by @dependabot[bot] in #155
  • chore: migrate sln to slnx by @guitarrapc in #157
  • ci: use NuGet Trusted Publish by @guitarrapc in #158
  • chore: nuget and sign key handling by @guitarrapc in #159
  • chore: use filescope by @guitarrapc in #160
  • chore: bump SkiaSharp packages to 3.119.1 by @guitarrapc in #161

Full Changelog: 0.7.0...0.8.0

0.7.0

13 Dec 19:15
e834ae3

Choose a tag to compare

Note

This release include security fix for 'SkiaSharp' 2.80.2, which has a known high severity vulnerability, GHSA-j7hp-h8jx-5ppr

What's Changed

New Contributors

Full Changelog: 0.6.0...0.7.0

0.6.0

05 May 09:18
432a503

Choose a tag to compare

Strong Name Assembly is supported.

ref: https://docs.microsoft.com/en-us/dotnet/standard/assembly/strong-named

What's Changed

New Contributors

  • @github-actions made their first contribution in #51

Full Changelog: 0.5.0...0.6.0

0.5.0

25 Apr 18:25
96d9eb4

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: 0.4.1...0.5.0

0.4.1

25 Nov 20:05
0d90ae4

Choose a tag to compare

This is Linux package dependency fix.

Feature

n/a

Fix

  • fix: libskiasharp dependency. SkiaSharp.QrCode 0.4.0 had explict dependency with SkiaSharp.NativeAssets.Linux 2.80.2, now it's removed.
    • side effect: Must explict add SkiaSharp.NativeAssets.Linux.NoDependencies or SkiaSharp.NativeAssets.Linux when running on Linux. refer README for more detail.

0.4.0

24 Nov 18:56
1e9cae0

Choose a tag to compare

Summary

Features

  • Added functionality to change the color of the qr code. (#10) thanks @AlexGipp
  • Added functionality to add icon to the center of the qr code. (#13) thanks @AlexGipp
  • bump SkiaSharp version from 1.68.0 to 2.80.2 (#17, #24)

Misc

  • add Unit Test for netcore31 and net50 (#22, #23)
  • switch ci to github actions (#24)

Samples

  • add NanoServer samples (#6)
  • add Color and Icon samples (#21)