Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/291 iconborderwidth doesnt work #351

Merged
merged 2 commits into from Nov 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 17 additions & 19 deletions QRCoder/QRCode.cs
Expand Up @@ -58,7 +58,7 @@ public Bitmap GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor,
return bmp;
}

public Bitmap GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, Bitmap icon=null, int iconSizePercent=15, int iconBorderWidth = 6, bool drawQuietZones = true)
public Bitmap GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, Bitmap icon=null, int iconSizePercent=15, int iconBorderWidth = 0, bool drawQuietZones = true, Color? iconBackgroundColor = null)
{
var size = (this.QrCodeData.ModuleMatrix.Count - (drawQuietZones ? 0 : 8)) * pixelsPerModule;
var offset = drawQuietZones ? 0 : 4 * pixelsPerModule;
Expand All @@ -72,36 +72,34 @@ public Bitmap GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor,
gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
gfx.CompositingQuality = CompositingQuality.HighQuality;
gfx.Clear(lightColor);

var drawIconFlag = icon != null && iconSizePercent > 0 && iconSizePercent <= 100;

GraphicsPath iconPath = null;
float iconDestWidth = 0, iconDestHeight = 0, iconX = 0, iconY = 0;

if (drawIconFlag)
{
iconDestWidth = iconSizePercent * bmp.Width / 100f;
iconDestHeight = drawIconFlag ? iconDestWidth * icon.Height / icon.Width : 0;
iconX = (bmp.Width - iconDestWidth) / 2;
iconY = (bmp.Height - iconDestHeight) / 2;

var centerDest = new RectangleF(iconX - iconBorderWidth, iconY - iconBorderWidth, iconDestWidth + iconBorderWidth * 2, iconDestHeight + iconBorderWidth * 2);
iconPath = this.CreateRoundedRectanglePath(centerDest, iconBorderWidth * 2);
}


for (var x = 0; x < size + offset; x = x + pixelsPerModule)
{
for (var y = 0; y < size + offset; y = y + pixelsPerModule)
{
var moduleBrush = this.QrCodeData.ModuleMatrix[(y + pixelsPerModule) / pixelsPerModule - 1][(x + pixelsPerModule) / pixelsPerModule - 1] ? darkBrush : lightBrush;

gfx.FillRectangle(moduleBrush , new Rectangle(x - offset, y - offset, pixelsPerModule, pixelsPerModule));
}
}

if (drawIconFlag)
{
float iconDestWidth = iconSizePercent * bmp.Width / 100f;
float iconDestHeight = drawIconFlag ? iconDestWidth * icon.Height / icon.Width : 0;
float iconX = (bmp.Width - iconDestWidth) / 2;
float iconY = (bmp.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);
var iconBgBrush = iconBackgroundColor != null ? new SolidBrush((Color)iconBackgroundColor) : lightBrush;
//Only render icon/logo background, if iconBorderWith is set > 0
if (iconBorderWidth > 0)
{
using (GraphicsPath iconPath = CreateRoundedRectanglePath(centerDest, iconBorderWidth * 2))
{
gfx.FillPath(iconBgBrush, iconPath);
}
}
gfx.DrawImage(icon, iconDestRect, new RectangleF(0, 0, icon.Width, icon.Height), GraphicsUnit.Pixel);
}

Expand Down Expand Up @@ -129,7 +127,7 @@ internal GraphicsPath CreateRoundedRectanglePath(RectangleF rect, int cornerRadi

public static class QRCodeHelper
{
public static Bitmap GetQRCode(string plainText, int pixelsPerModule, Color darkColor, Color lightColor, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1, Bitmap icon = null, int iconSizePercent = 15, int iconBorderWidth = 6, bool drawQuietZones = true)
public static Bitmap GetQRCode(string plainText, int pixelsPerModule, Color darkColor, Color lightColor, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1, Bitmap 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))
Expand Down
128 changes: 104 additions & 24 deletions QRCoderTests/QRCodeRendererTests.cs
Expand Up @@ -19,7 +19,7 @@ public class QRCodeRendererTests
#if !NETCOREAPP1_1
[Fact]
[Category("QRRenderer/QRCode")]
public void can_create_standard_qrcode_graphic()
public void can_create_qrcode_standard_graphic()
{
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);
Expand All @@ -28,10 +28,36 @@ public void can_create_standard_qrcode_graphic()
var result = HelperFunctions.BitmapToHash(bmp);
result.ShouldBe("e8c61b8f0455924fe08ba68686d0d296");
}
#endif

[Fact]
[Category("QRRenderer/QRCode")]
public void can_create_qrcode_standard_graphic_hex()
{
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);
var bmp = new QRCode(data).GetGraphic(10, "#000000", "#ffffff");

var result = HelperFunctions.BitmapToHash(bmp);
result.ShouldBe("e8c61b8f0455924fe08ba68686d0d296");
}


[Fact]
[Category("QRRenderer/QRCode")]
public void can_create_qrcode_standard_graphic_without_quietzones()
{
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);
var bmp = new QRCode(data).GetGraphic(5, Color.Black, Color.White, false);

var result = HelperFunctions.BitmapToHash(bmp);
#if NET35_OR_GREATER || NET40_OR_GREATER
result.ShouldBe("329e1664f57cbe7332d8d4db04c1d480");
#else
result.ShouldBe("d703e54a0ba541c6ea69e3d316e394e7");
#endif
}

#if !NETCOREAPP1_1 && !NETCOREAPP2_0

[Fact]
[Category("QRRenderer/QRCode")]
Expand All @@ -43,7 +69,6 @@ public void can_create_qrcode_with_transparent_logo_graphic()

var bmp = new QRCode(data).GetGraphic(10, Color.Black, Color.Transparent, icon: (Bitmap)Image.FromFile(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png"));
//Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346

var result = HelperFunctions.BitmapToHash(bmp);
#if NET35_OR_GREATER || NET40_OR_GREATER
result.ShouldBe("ee65d96c3013f6032b561cc768251eef");
Expand All @@ -70,28 +95,83 @@ public void can_create_qrcode_with_non_transparent_logo_graphic()
#endif
}

/*
private static byte[] PixelsToAveragedByteArray(Bitmap bmp)
[Fact]
[Category("QRRenderer/QRCode")]
public void can_create_qrcode_with_logo_and_with_transparent_border()
{
//Create QR code
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);

var logo = (Bitmap)Image.FromFile(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png");
var bmp = new QRCode(data).GetGraphic(10, Color.Black, Color.Transparent, icon: logo, iconBorderWidth: 6);
//Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346
var result = HelperFunctions.BitmapToHash(bmp);
#if NET35_OR_GREATER || NET40_OR_GREATER
result.ShouldBe("ee65d96c3013f6032b561cc768251eef");
#else
result.ShouldBe("150f8fc7dae4487ba2887d2b2bea1c25");
#endif
}

[Fact]
[Category("QRRenderer/QRCode")]
public void can_create_qrcode_with_logo_and_with_standard_border()
{
//Create QR code
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);

var logo = (Bitmap)Image.FromFile(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png");
var bmp = new QRCode(data).GetGraphic(10, Color.Black, Color.White, icon: logo, iconBorderWidth: 6);
//Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346
var result = HelperFunctions.BitmapToHash(bmp);
#if NET35_OR_GREATER || NET40_OR_GREATER
result.ShouldBe("52207bd86ca5a532fb2095dbaa0ae04c");
#else
result.ShouldBe("1c926ea1d48f42fdf8e6f1438b774cdd");
#endif
}

[Fact]
[Category("QRRenderer/QRCode")]
public void can_create_qrcode_with_logo_and_with_custom_border()
{
//Re-color
var bmpTmp = new Bitmap(bmp.Width, bmp.Height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
using (var gr = Graphics.FromImage(bmp))
gr.DrawImage(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));

//Downscale
var bmpSmall = new Bitmap(bmpTmp, new Size(16, 16));

var bytes = new System.Collections.Generic.List<byte>();
for (int x = 0; x < bmpSmall.Width; x++)
{
for (int y = 0; y < bmpSmall.Height; y++)
{
bytes.AddRange(new byte[] { bmpSmall.GetPixel(x, y).R, bmpSmall.GetPixel(x, y).G, bmpSmall.GetPixel(x, y).B });
}
}
return bytes.ToArray();
//Create QR code
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);

var logo = (Bitmap)Image.FromFile(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png");
var bmp = new QRCode(data).GetGraphic(10, Color.Black, Color.Transparent, icon: logo, iconBorderWidth: 6, iconBackgroundColor: Color.DarkGreen);
//Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346
var result = HelperFunctions.BitmapToHash(bmp);
#if NET35_OR_GREATER || NET40_OR_GREATER
result.ShouldBe("d2f20d34a973d92b9c3e05db1393b331");
#else
result.ShouldBe("9a06bfbb72df999b6290b5af5c4037cb");
#endif
}


[Fact]
[Category("QRRenderer/QRCode")]
public void can_instantate_qrcode_parameterless()
{
var svgCode = new QRCode();
svgCode.ShouldNotBeNull();
svgCode.ShouldBeOfType<QRCode>();
}

[Fact]
[Category("QRRenderer/QRCode")]
public void can_render_qrcode_from_helper()
{
//Create QR code
var bmp = QRCodeHelper.GetQRCode("This is a quick test! 123#?", 10, Color.Black, Color.White, QRCodeGenerator.ECCLevel.H);

var result = HelperFunctions.BitmapToHash(bmp);
result.ShouldBe("e8c61b8f0455924fe08ba68686d0d296");
}
*/
#endif
}
}