Skip to content

Commit

Permalink
Merge pull request #351 from codebude/bugfix/291-iconborderwidth-does…
Browse files Browse the repository at this point in the history
…nt-work

Bugfix/291 iconborderwidth doesnt work
  • Loading branch information
codebude committed Nov 23, 2021
2 parents c9314f9 + 940798b commit f10daa1
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 43 deletions.
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
}
}

0 comments on commit f10daa1

Please sign in to comment.