diff --git a/QRCoder/Base64QRCode.cs b/QRCoder/Base64QRCode.cs
index 539af073..a35d9970 100644
--- a/QRCoder/Base64QRCode.cs
+++ b/QRCoder/Base64QRCode.cs
@@ -3,7 +3,6 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
-using static QRCoder.Base64QRCode;
using static QRCoder.QRCodeGenerator;
namespace QRCoder
@@ -88,13 +87,6 @@ private string BitmapToBase64(Bitmap bmp, ImageType imgType)
return base64;
}
- public enum ImageType
- {
- Gif,
- Jpeg,
- Png
- }
-
}
#if NET6_0_WINDOWS
diff --git a/QRCoder/ImageSharp/Base64QRCode.cs b/QRCoder/ImageSharp/Base64QRCode.cs
new file mode 100644
index 00000000..c58feb56
--- /dev/null
+++ b/QRCoder/ImageSharp/Base64QRCode.cs
@@ -0,0 +1,104 @@
+using System;
+using System.IO;
+using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.Formats;
+using static QRCoder.QRCodeGenerator;
+
+namespace QRCoder.ImageSharp
+{
+ public class Base64QRCode : AbstractQRCode, IDisposable
+ {
+ private QRCode qr;
+
+ ///
+ /// Constructor without params to be used in COM Objects connections
+ ///
+ public Base64QRCode()
+ {
+ qr = new QRCode();
+ }
+
+ public Base64QRCode(QRCodeData data)
+ : base(data)
+ {
+ qr = new QRCode(data);
+ }
+
+ public override void SetQRCodeData(QRCodeData data)
+ {
+ qr.SetQRCodeData(data);
+ }
+
+ public string GetGraphic(int pixelsPerModule)
+ {
+ return GetGraphic(pixelsPerModule, Color.Black, Color.White, true);
+ }
+
+ public string GetGraphic(int pixelsPerModule, string darkColorHtmlHex, string lightColorHtmlHex, bool drawQuietZones = true, ImageType imgType = ImageType.Png)
+ {
+ return GetGraphic(pixelsPerModule, Color.Parse(darkColorHtmlHex), Color.Parse(lightColorHtmlHex), drawQuietZones, imgType);
+ }
+
+ public string GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, bool drawQuietZones = true, ImageType imgType = ImageType.Png)
+ {
+ var base64 = string.Empty;
+ using (Image img = qr.GetGraphic(pixelsPerModule, darkColor, lightColor, drawQuietZones))
+ {
+ base64 = BitmapToBase64(img, imgType);
+ }
+
+ return base64;
+ }
+
+ public string GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, Image icon, int iconSizePercent = 15, int iconBorderWidth = 6, bool drawQuietZones = true, ImageType imgType = ImageType.Png)
+ {
+ var base64 = string.Empty;
+ using (Image bmp = qr.GetGraphic(pixelsPerModule, darkColor, lightColor, icon, iconSizePercent, iconBorderWidth, drawQuietZones))
+ {
+ base64 = BitmapToBase64(bmp, imgType);
+ }
+
+ return base64;
+ }
+
+ private string BitmapToBase64(Image img, ImageType imgType)
+ {
+ var base64 = string.Empty;
+ IImageEncoder iFormat;
+ switch (imgType)
+ {
+ default:
+ case ImageType.Png:
+ iFormat = new SixLabors.ImageSharp.Formats.Png.PngEncoder();
+ break;
+ case ImageType.Jpeg:
+ iFormat = new SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder();
+ break;
+ case ImageType.Gif:
+ iFormat = new SixLabors.ImageSharp.Formats.Gif.GifEncoder();
+ break;
+ }
+
+ using (var memoryStream = new MemoryStream())
+ {
+ img.Save(memoryStream, iFormat);
+ base64 = Convert.ToBase64String(memoryStream.ToArray(), Base64FormattingOptions.None);
+ }
+
+ return base64;
+ }
+ }
+
+ public static class ImageSharpBase64QRCodeHelper
+ {
+ public static string GetQRCode(string plainText, int pixelsPerModule, string darkColorHtmlHex, string lightColorHtmlHex, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1, bool drawQuietZones = true, ImageType imgType = ImageType.Png)
+ {
+ using (var qrGenerator = new QRCodeGenerator())
+ using (var qrCodeData = qrGenerator.CreateQrCode(plainText, eccLevel, forceUtf8, utf8BOM, eciMode, requestedVersion))
+ using (var qrCode = new Base64QRCode(qrCodeData))
+ {
+ return qrCode.GetGraphic(pixelsPerModule, darkColorHtmlHex, lightColorHtmlHex, drawQuietZones, imgType);
+ }
+ }
+ }
+}
diff --git a/QRCoder/ImageSharp/QRCode.cs b/QRCoder/ImageSharp/QRCode.cs
new file mode 100644
index 00000000..f3c5b25c
--- /dev/null
+++ b/QRCoder/ImageSharp/QRCode.cs
@@ -0,0 +1,129 @@
+using System;
+using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing;
+using static QRCoder.QRCodeGenerator;
+
+namespace QRCoder.ImageSharp
+{
+ public class QRCode : AbstractQRCode, IDisposable
+ {
+ ///
+ /// Constructor without params to be used in COM Objects connections
+ ///
+ public QRCode() { }
+
+ public QRCode(QRCodeData data)
+ : base(data) { }
+
+ public Image GetGraphic(int pixelsPerModule)
+ {
+ return GetGraphic(pixelsPerModule, Color.Black, Color.White, true);
+ }
+
+ public Image GetGraphic(int pixelsPerModule, string darkColorHtmlHex, string lightColorHtmlHex, bool drawQuietZones = true)
+ {
+ return GetGraphic(pixelsPerModule, Color.Parse(darkColorHtmlHex), Color.Parse(lightColorHtmlHex), drawQuietZones);
+ }
+
+ public Image GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, bool drawQuietZones = true)
+ {
+ var moduleOffset = drawQuietZones ? 0 : 4;
+ var size = (QrCodeData.ModuleMatrix.Count - (moduleOffset * 2)) * pixelsPerModule;
+
+ var image = new Image(size, size);
+ DrawQRCode(image, pixelsPerModule, moduleOffset, darkColor, lightColor);
+
+ return image;
+ }
+
+ public Image GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, Image icon = null, int iconSizePercent = 15, int iconBorderWidth = 0, bool drawQuietZones = true, Color? iconBackgroundColor = null)
+ {
+ var img = GetGraphic(pixelsPerModule, darkColor, lightColor, drawQuietZones) as Image;
+ if (icon != null && iconSizePercent > 0 && iconSizePercent <= 100)
+ {
+ var iconDestWidth = iconSizePercent * img.Width / 100f;
+ var iconDestHeight = iconDestWidth * icon.Height / icon.Width;
+ var iconX = (img.Width - iconDestWidth) / 2;
+ var iconY = (img.Height - iconDestHeight) / 2;
+ var centerDest = new RectangleF(iconX - iconBorderWidth, iconY - iconBorderWidth, iconDestWidth + (iconBorderWidth * 2), iconDestHeight + (iconBorderWidth * 2));
+ var iconDestRect = new RectangleF(iconX, iconY, iconDestWidth, iconDestHeight);
+
+ if (iconBorderWidth > 0)
+ {
+ if (!iconBackgroundColor.HasValue)
+ {
+ iconBackgroundColor = lightColor;
+ }
+
+ if (iconBackgroundColor != Color.Transparent)
+ {
+ img.ProcessPixelRows(accessor =>
+ {
+ for (var y = (int)centerDest.Top; y <= (int)centerDest.Bottom; y++)
+ {
+ var pixelRow = accessor.GetRowSpan(y);
+
+ for (var x = (int)centerDest.Left; x <= (int)centerDest.Right; x++)
+ {
+ pixelRow[x] = iconBackgroundColor ?? lightColor;
+ }
+ }
+ });
+ }
+ }
+
+ var sizedIcon = icon.Clone(x => x.Resize((int)iconDestWidth, (int)iconDestHeight));
+ img.Mutate(x => x.DrawImage(sizedIcon, new Point((int)iconDestRect.X, (int)iconDestRect.Y), 1));
+ }
+
+ return img;
+ }
+
+ private void DrawQRCode(Image image, int pixelsPerModule, int moduleOffset, Color darkColor, Color lightColor)
+ {
+ var row = new Rgba32[image.Width];
+
+ image.ProcessPixelRows(accessor =>
+ {
+ for (var modY = moduleOffset; modY < QrCodeData.ModuleMatrix.Count - moduleOffset; modY++)
+ {
+ // Generate row for this y-Module
+ for (var modX = moduleOffset; modX < QrCodeData.ModuleMatrix.Count - moduleOffset; modX++)
+ {
+ for (var idx = 0; idx < pixelsPerModule; idx++)
+ {
+ row[((modX - moduleOffset) * pixelsPerModule) + idx] = this.QrCodeData.ModuleMatrix[modY][modX] ? darkColor : lightColor;
+ }
+ }
+
+ // Copy the prepared row to the image
+ for (var idx = 0; idx < pixelsPerModule; idx++)
+ {
+ var pixelRow = accessor.GetRowSpan(((modY - moduleOffset) * pixelsPerModule) + idx);
+ row.CopyTo(pixelRow);
+ }
+ }
+ });
+ }
+ }
+
+ public static class ImageSharpQRCodeHelper
+ {
+ public static Image GetQRCode(string plainText, int pixelsPerModule, Color darkColor, Color lightColor, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1, Image icon = null, int iconSizePercent = 15, int iconBorderWidth = 0, bool drawQuietZones = true)
+ {
+ using (var qrGenerator = new QRCodeGenerator())
+ using (var qrCodeData = qrGenerator.CreateQrCode(plainText, eccLevel, forceUtf8, utf8BOM, eciMode, requestedVersion))
+ using (var qrCode = new QRCode(qrCodeData))
+ {
+ return qrCode.GetGraphic(pixelsPerModule,
+ darkColor,
+ lightColor,
+ icon,
+ iconSizePercent,
+ iconBorderWidth,
+ drawQuietZones);
+ }
+ }
+ }
+}
diff --git a/QRCoder/ImageType.cs b/QRCoder/ImageType.cs
new file mode 100644
index 00000000..72568dca
--- /dev/null
+++ b/QRCoder/ImageType.cs
@@ -0,0 +1,9 @@
+namespace QRCoder
+{
+ public enum ImageType
+ {
+ Gif,
+ Jpeg,
+ Png
+ }
+}
diff --git a/QRCoder/QRCoder.csproj b/QRCoder/QRCoder.csproj
index d67a7989..f055f64f 100644
--- a/QRCoder/QRCoder.csproj
+++ b/QRCoder/QRCoder.csproj
@@ -4,7 +4,7 @@
net35;net40;netstandard1.3;netstandard2.0;net5.0;net5.0-windows;net6.0;net6.0-windows
false
$(DefineConstants);NET5_0_WINDOWS
- $(DefineConstants);NET6_0_WINDOWS
+ $(DefineConstants);NET6_0_WINDOWS
false
true
@@ -48,9 +48,17 @@
-
-
-
+
+
+
+
+
+
+
+
+
+
+
$(MSBuildProgramFiles32)\Reference Assemblies\Microsoft\Framework\.NETFramework\v3.5\Profile\Client
diff --git a/QRCoderConsole/Program.cs b/QRCoderConsole/Program.cs
index e9af916a..130ce4d2 100644
--- a/QRCoderConsole/Program.cs
+++ b/QRCoderConsole/Program.cs
@@ -1,5 +1,15 @@
using System;
+#if !IMAGE_SHARP
using System.Drawing.Imaging;
+#else
+using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.Formats;
+using SixLabors.ImageSharp.Formats.Jpeg;
+using SixLabors.ImageSharp.Formats.Png;
+using SixLabors.ImageSharp.Formats.Gif;
+using SixLabors.ImageSharp.Formats.Bmp;
+using SixLabors.ImageSharp.Formats.Tiff;
+#endif
using System.IO;
using NDesk.Options;
using QRCoderConsole.DataObjects;
@@ -147,6 +157,7 @@ private static void GenerateQRCode(string payloadString, QRCodeGenerator.ECCLeve
case SupportedImageFormat.Gif:
case SupportedImageFormat.Bmp:
case SupportedImageFormat.Tiff:
+#if !IMAGE_SHARP
using (var code = new QRCode(data))
{
using (var bitmap = code.GetGraphic(pixelsPerModule, foreground, background, true))
@@ -155,6 +166,17 @@ private static void GenerateQRCode(string payloadString, QRCodeGenerator.ECCLeve
bitmap.Save(outputFileName, actualFormat);
}
}
+#else
+ using (var code = new QRCoder.ImageSharp.QRCode(data))
+ {
+ using (var bitmap = code.GetGraphic(pixelsPerModule, foreground, background, true))
+ {
+ var actualFormat = new OptionSetter().GetImageFormat(imgFormat.ToString());
+ bitmap.Save(outputFileName, actualFormat);
+ }
+ }
+#endif
+
break;
case SupportedImageFormat.Svg:
using (var code = new SvgQRCode(data))
@@ -251,9 +273,7 @@ public QRCodeGenerator.ECCLevel GetECCLevel(string value)
return level;
}
-#if NET6_0_WINDOWS
- [System.Runtime.Versioning.SupportedOSPlatform("windows")]
-#endif
+#if !IMAGE_SHARP
public ImageFormat GetImageFormat(string value)
{
switch (value.ToLower())
@@ -273,6 +293,27 @@ public ImageFormat GetImageFormat(string value)
return ImageFormat.Png;
}
}
+#else
+ public IImageEncoder GetImageFormat(string value)
+ {
+ switch (value.ToLower())
+ {
+ case "jpg":
+ return new JpegEncoder();
+ case "jpeg":
+ return new PngEncoder();
+ case "gif":
+ return new GifEncoder();
+ case "bmp":
+ return new BmpEncoder();
+ case "tiff":
+ return new TiffEncoder();
+ case "png":
+ default:
+ return new PngEncoder();
+ }
+ }
+#endif
}
}
diff --git a/QRCoderConsole/QRCoderConsole.csproj b/QRCoderConsole/QRCoderConsole.csproj
index 94c07191..24fa14c8 100644
--- a/QRCoderConsole/QRCoderConsole.csproj
+++ b/QRCoderConsole/QRCoderConsole.csproj
@@ -5,7 +5,8 @@
true
$(DefineConstants);NET5_0_WINDOWS
- $(DefineConstants);NET6_0_WINDOWS
+ $(DefineConstants);NET6_0_WINDOWS
+ $(DefineConstants);IMAGE_SHARP
true
Exe
false
diff --git a/readme.md b/readme.md
index 7ffdda2f..521364bc 100644
--- a/readme.md
+++ b/readme.md
@@ -84,6 +84,8 @@ Besides the normal QRCode class (which is shown in the example above) for creati
* [SvgQRCode](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#26-svgqrcode-renderer-in-detail)
* [UnityQRCode](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#27-unityqrcode-renderer-in-detail) (_via [QRCoder.Unity](https://www.nuget.org/packages/QRCoder.Unity)_)
* [XamlQRCode](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#28-xamlqrcode-renderer-in-detail) (_via [QRCoder.Xaml](https://www.nuget.org/packages/QRCoder.Xaml)_)
+* ImageSharp.QRCode (repeats logic of QRCode but uses ImageSharp under the hood)
+* ImageSharp.Base64QRCode (repeats logic of Base64QRCode but uses ImageSharp under the hood)
*Note: Please be aware that not all renderers are available on all target frameworks. Please check the [compatibility table](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#2-overview-of-the-different-renderers) in our wiki, to see if a specific renderer is available on your favourite target framework.*