Skip to content

0.9.0

Choose a tag to compare

@github-actions github-actions released this 25 Oct 08:54
· 272 commits to main since this release
7a749a6

🎉 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)
  • QRCodeGenerator.CreateQrCode text API now forwards to binary API (#258)

Module Placement Improvements

  • Internalized ModulePlacer (#190)
  • Changed ModulePlacer receiver from ref QRCodeData to Span<byte> (#235)
  • Used span instead of static field header signature (#201)

Code Quality

  • Enabled ImplicitUsings (#181)
  • Enabled Nullable (#182)
  • Refactored and optimized QR code constants (#167)

🛠️ Development Environment

  • .NET 9.0 support (#170)
  • Added .NET 8.0, handling .NET 5 or greater (#227)
  • NativeAOT support (#267)
  • Added benchmarks (#163, #226)
  • Added README to NuGet (#162)
  • Updated README (#270)

🔗 Links

Full Changelog: 0.8.0...0.9.0