Skip to content

Implementation of ByteMatrixQRCode #449

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 140 additions & 0 deletions QRCoder/ByteMatrixQRCode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
using System;
using System.Collections.Generic;
using static QRCoder.QRCodeGenerator;

namespace QRCoder
{
public class ByteMatrixQRCode : AbstractQRCode, IDisposable
{
/// <summary>
/// Constructor without params to be used in COM Objects connections
/// </summary>
public ByteMatrixQRCode()
{
}

/// <summary>
/// Initialises a new <see cref="ByteMatrixQRCode"/> instance, referencing the supplied QR Code data to read and return its contents in a byte matrix format,
/// representing the whitespace and dark modules that make up the QR Code.
/// </summary>
/// <param name="data"><see cref="QRCodeData"/> generated by the <see cref="QRCodeGenerator"/>.</param>
public ByteMatrixQRCode(QRCodeData data)
: base(data)
{
}

/// <summary>
/// Gets the QR Code byte matrix as a single string, separated by the end of line character. Specifying a larger pixel value will repeat modules to the required scale.
/// The <see cref="AsciiQRCode"/> provides better flexibility of string QR Code output - this method is intended as a text representation of the calculated QR Code byte matrix.
/// </summary>
/// <param name="pixelsPerModule">Number of repeated pixels per module.</param>
/// <param name="drawQuietZones">Whether the quiet zone should be drawn around the QR Code string output. (Default: true)</param>
/// <param name="endOfLine">End of line separator. (Default: \n)</param>
/// <returns>A string representation of the QR Code byte matrix, separated by the end of line character and sized using the supplied pixels per module.</returns>
public string GetGraphic(int pixelsPerModule = 1, bool drawQuietZones = true, string endOfLine = "\n")
{
byte[,] byteMatrix = GetByteMatrix(drawQuietZones);

if (byteMatrix == null)
{
return null;
}

if (pixelsPerModule > 1)
{
byteMatrix = IncreasePixels(byteMatrix, pixelsPerModule);
}

List<string> byteMatrixContent = new List<string>();

for (int i = 0; i < byteMatrix.GetLength(0); i++)
{
string line = string.Empty;

for (int j = 0; j < byteMatrix.GetLength(1); j++)
{
line += byteMatrix[i, j];
}

byteMatrixContent.Add(line);
}

return string.Join(endOfLine, byteMatrixContent.ToArray());
}

/// <summary>
/// Gets the QR Code in a byte matrix format, representing the whitespace and dark modules that make up the QR Code.
/// </summary>
/// <param name="drawQuietZones">Whether the quiet zone should be included in the byte matrix output. (Default: true)</param>
/// <returns>A byte matrix representation of the generated QR Code.</returns>
public byte[,] GetByteMatrix(bool drawQuietZones = true)
{
int paddingToRemove = drawQuietZones ? 0 : 4;
int totalPaddingToRemove = paddingToRemove * 2;

if (!(QrCodeData?.ModuleMatrix?.Count > totalPaddingToRemove))
{
return null;
}

int matrixSize = QrCodeData.ModuleMatrix.Count - totalPaddingToRemove;

byte[,] byteMatrix = new byte[matrixSize, matrixSize];

for (int i = 0; i < matrixSize; i++)
{
for (int j = 0; j < matrixSize; j++)
{
byteMatrix[i, j] = (byte)(QrCodeData.ModuleMatrix[j + paddingToRemove][i + paddingToRemove] ? 1 : 0);
}
}

return byteMatrix;
}

private byte[,] IncreasePixels(byte[,] input, int pixelIncrease)
{
int width = input.GetLength(0);
int height = input.GetLength(1);

byte[,] output = new byte[width * pixelIncrease, height * pixelIncrease];

for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
byte pixelValue = input[i, j];

for (int x = 0; x < pixelIncrease; x++)
{
for (int y = 0; y < pixelIncrease; y++)
{
output[i * pixelIncrease + x, j * pixelIncrease + y] = pixelValue;
}
}
}
}

return output;
}
}

public static class ByteMatrixQRCodeHelper
{
public static string GetQRCode(string plainText, int pixelsPerModule, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1, string endOfLine = "\n", bool drawQuietZones = true)
{
using (var qrGenerator = new QRCodeGenerator())
using (var qrCodeData = qrGenerator.CreateQrCode(plainText, eccLevel, forceUtf8, utf8BOM, eciMode, requestedVersion))
using (var qrCode = new ByteMatrixQRCode(qrCodeData))
return qrCode.GetGraphic(pixelsPerModule, drawQuietZones, endOfLine);
}

public static byte[,] GetQRCodeByteMatrix(string plainText, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1, string endOfLine = "\n", bool drawQuietZones = true)
{
using (var qrGenerator = new QRCodeGenerator())
using (var qrCodeData = qrGenerator.CreateQrCode(plainText, eccLevel, forceUtf8, utf8BOM, eciMode, requestedVersion))
using (var qrCode = new ByteMatrixQRCode(qrCodeData))
return qrCode.GetByteMatrix(drawQuietZones);
}
}
}
Loading