The modulation matrix contains the modulation for each black/white cell of barcode matrix and quiet zone.
The modulation value is a number defined in range from -1 to 1:
Here is an example that demonstrates how to draw modulation matrix of the matrix 2D barcode (Aztec, DataMatrix, QR, MicroQR and Han Xin Code):
''' <summary>
''' Test that shows how to draw modulation matrix of the matrix 2D barcode
''' (Aztec, DataMatrix, Han Xin Code, QR and MicroQR) on the bitmap.
''' </summary>
Class ISO15415QualityTestModulationMatrixExample
''' <summary>
''' Runs the test.
''' </summary>
Public Shared Sub Test()
' load image with barcode from file
Using barcodeImage As Vintasoft.Imaging.VintasoftBitmap = Vintasoft.Barcode.ImageCodecs.[Default].Decode("testModulationMatrix.jpg")
' read barcodes from image and create the modulation matrix image
Dim bitmap As System.Drawing.Bitmap = ReadBarcodesAndCreateModulationMatrixImage(barcodeImage)
If bitmap Is Nothing Then
Throw New System.Exception()
End If
bitmap.Save("ModulationMatrix.png")
End Using
End Sub
''' <summary>
''' Reads barcodes from image, tests the print quality of 2D barcodes and creates the modulation matrix image.
''' </summary>
Public Shared Function ReadBarcodesAndCreateModulationMatrixImage(imageWithBarcodes As Vintasoft.Imaging.VintasoftBitmap) As System.Drawing.Bitmap
' create the barcode reader
Using reader As New Vintasoft.Barcode.BarcodeReader()
' specify that reader must collect information for barcode print quality test
reader.Settings.CollectTestInformation = True
' specify that reader must search for Aztec, DataMatrix, Han Xin Code, QR and MicroQR barcodes only
reader.Settings.ScanBarcodeTypes = Vintasoft.Barcode.BarcodeType.Aztec Or Vintasoft.Barcode.BarcodeType.DataMatrix Or Vintasoft.Barcode.BarcodeType.QR Or Vintasoft.Barcode.BarcodeType.MicroQR Or Vintasoft.Barcode.BarcodeType.HanXinCode
' recognize barcodes on image
Dim barcodeInfos As Vintasoft.Barcode.IBarcodeInfo() = reader.ReadBarcodes(imageWithBarcodes)
' test print quality of first recognized barcode using ISO 15415 test
Dim test As New Vintasoft.Barcode.QualityTests.ISO15415QualityTest()
test.CalculateGrades(DirectCast(barcodeInfos(0), Vintasoft.Barcode.BarcodeInfo.BarcodeInfo2D), imageWithBarcodes)
' create modulation matrix image
Return CreateModulationMatrixImage(test, 16, 128)
End Using
End Function
''' <summary>
''' Creates the modulation matrix image.
''' </summary>
''' <param name="qualityTest">The barcode print quality test.</param>
''' <param name="cellSize">The cell size.</param>
''' <param name="modulationAlpha">The modulation alpha.</param>
''' <returns>The bitmap.</returns>
Private Shared Function CreateModulationMatrixImage(qualityTest As Vintasoft.Barcode.QualityTests.ISO15415QualityTest, cellSize As Integer, modulationAlpha As Integer) As System.Drawing.Bitmap
Dim fontSize As Single = cellSize * 0.35F
Dim textFont As System.Drawing.Font = Nothing
Dim format As System.Drawing.StringFormat = Nothing
If fontSize > 5 Then
textFont = New System.Drawing.Font(System.Drawing.SystemFonts.DefaultFont.FontFamily, fontSize)
format = New System.Drawing.StringFormat()
format.Alignment = System.Drawing.StringAlignment.Center
format.LineAlignment = System.Drawing.StringAlignment.Center
End If
Dim modulationMatrix As Single(,) = qualityTest.ModulationMatrix
Dim matrixHeight As Integer = modulationMatrix.GetLength(0)
Dim matrixWidth As Integer = modulationMatrix.GetLength(1)
' create bitmap
Dim result As New System.Drawing.Bitmap(matrixWidth * cellSize, matrixHeight * cellSize, System.Drawing.Imaging.PixelFormat.Format24bppRgb)
' draw modulation matrix
Using foreBrush As New System.Drawing.SolidBrush(System.Drawing.Color.White)
Using g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(result)
For y As Integer = 0 To matrixHeight - 1
For x As Integer = 0 To matrixWidth - 1
Dim rect As New System.Drawing.RectangleF(x * cellSize, y * cellSize, cellSize, cellSize)
Dim modulation As Single = modulationMatrix(y, x)
' background
Dim backBrush As System.Drawing.Brush = If(modulation < 0, System.Drawing.Brushes.White, System.Drawing.Brushes.Black)
g.FillRectangle(backBrush, rect)
' modulation highlight
foreBrush.Color = System.Drawing.Color.FromArgb(modulationAlpha, GetColor(System.Math.Abs(modulation)))
g.FillRectangle(foreBrush, rect)
If textFont IsNot Nothing Then
' modulation percent
Dim text As String = System.Math.Round(System.Math.Abs(modulation) * 100).ToString()
Dim textBrush As System.Drawing.Brush = If(modulation >= 0, System.Drawing.Brushes.White, System.Drawing.Brushes.Black)
g.DrawString(text, textFont, textBrush, rect, format)
End If
Next
Next
End Using
End Using
If textFont IsNot Nothing Then
textFont.Dispose()
End If
Return result
End Function
''' <summary>
''' Returns the color grade of cell modulation.
''' </summary>
''' <param name="modulation">The cell modulation.</param>
''' <returns>The color.</returns>
Private Shared Function GetColor(modulation As Single) As System.Drawing.Color
Dim hiColor As System.Drawing.Color = System.Drawing.Color.FromArgb(0, 192, 0)
Dim threshold1 As Single = 0.5F
Dim threshold1Color As System.Drawing.Color = System.Drawing.Color.FromArgb(128, 192, 0)
Dim threshold2 As Single = 0.3F
Dim threshold2Color As System.Drawing.Color = System.Drawing.Color.Orange
Dim lowColor As System.Drawing.Color = System.Drawing.Color.Red
If modulation >= threshold1 Then
Return GetInterpolatedColor(threshold1, threshold1Color, 1, hiColor, modulation)
End If
If modulation >= threshold2 Then
Return GetInterpolatedColor(threshold2, threshold2Color, threshold1, threshold1Color, modulation)
End If
Return GetInterpolatedColor(0, lowColor, threshold2, threshold2Color, modulation)
End Function
''' <summary>
''' Returns the interpolated color for specified value.
''' </summary>
''' <param name="min">The minimum value.</param>
''' <param name="minColor">Color for minimum value.</param>
''' <param name="max">The maximum value.</param>
''' <param name="maxColor">Color for maximum value.</param>
''' <param name="value">The value.</param>
''' <returns>The interpolated color for <i>value</i>.</returns>
Private Shared Function GetInterpolatedColor(min As Single, minColor As System.Drawing.Color, max As Single, maxColor As System.Drawing.Color, value As Single) As System.Drawing.Color
Dim scale As Single = (value - min) / (max - min)
Dim r As Single = minColor.R * (1 - scale) + maxColor.R * scale
Dim g As Single = minColor.G * (1 - scale) + maxColor.G * scale
Dim b As Single = minColor.B * (1 - scale) + maxColor.B * scale
Return System.Drawing.Color.FromArgb(CInt(Math.Truncate(System.Math.Round(r))), CInt(Math.Truncate(System.Math.Round(g))), CInt(Math.Truncate(System.Math.Round(b))))
End Function
End Class
/// <summary>
/// Test that shows how to draw modulation matrix of the matrix 2D barcode
/// (Aztec, DataMatrix, Han Xin Code, QR and MicroQR) on the bitmap.
/// </summary>
class ISO15415QualityTestModulationMatrixExample
{
/// <summary>
/// Runs the test.
/// </summary>
public static void Test()
{
// load image with barcode from file
using (Vintasoft.Imaging.VintasoftBitmap barcodeImage = Vintasoft.Barcode.ImageCodecs.Default.Decode("testModulationMatrix.jpg"))
{
// read barcodes from image and create the modulation matrix image
System.Drawing.Bitmap bitmap = ReadBarcodesAndCreateModulationMatrixImage(barcodeImage);
if (bitmap == null)
throw new System.Exception();
bitmap.Save("ModulationMatrix.png");
}
}
/// <summary>
/// Reads barcodes from image, tests the print quality of 2D barcodes and creates the modulation matrix image.
/// </summary>
public static System.Drawing.Bitmap ReadBarcodesAndCreateModulationMatrixImage(Vintasoft.Imaging.VintasoftBitmap imageWithBarcodes)
{
// create the barcode reader
using (Vintasoft.Barcode.BarcodeReader reader = new Vintasoft.Barcode.BarcodeReader())
{
// specify that reader must collect information for barcode print quality test
reader.Settings.CollectTestInformation = true;
// specify that reader must search for Aztec, DataMatrix, Han Xin Code, QR and MicroQR barcodes only
reader.Settings.ScanBarcodeTypes =
Vintasoft.Barcode.BarcodeType.Aztec | Vintasoft.Barcode.BarcodeType.DataMatrix |
Vintasoft.Barcode.BarcodeType.QR | Vintasoft.Barcode.BarcodeType.MicroQR | Vintasoft.Barcode.BarcodeType.HanXinCode;
// recognize barcodes on image
Vintasoft.Barcode.IBarcodeInfo[] barcodeInfos = reader.ReadBarcodes(imageWithBarcodes);
// test print quality of first recognized barcode using ISO 15415 test
Vintasoft.Barcode.QualityTests.ISO15415QualityTest test = new Vintasoft.Barcode.QualityTests.ISO15415QualityTest();
test.CalculateGrades((Vintasoft.Barcode.BarcodeInfo.BarcodeInfo2D)barcodeInfos[0], imageWithBarcodes);
// create modulation matrix image
return CreateModulationMatrixImage(test, 16, 128);
}
}
/// <summary>
/// Creates the modulation matrix image.
/// </summary>
/// <param name="qualityTest">The barcode print quality test.</param>
/// <param name="cellSize">The cell size.</param>
/// <param name="modulationAlpha">The modulation alpha.</param>
/// <returns>The bitmap.</returns>
private static System.Drawing.Bitmap CreateModulationMatrixImage(
Vintasoft.Barcode.QualityTests.ISO15415QualityTest qualityTest,
int cellSize,
int modulationAlpha)
{
float fontSize = cellSize * 0.35f;
System.Drawing.Font textFont = null;
System.Drawing.StringFormat format = null;
if (fontSize > 5)
{
textFont = new System.Drawing.Font(System.Drawing.SystemFonts.DefaultFont.FontFamily, fontSize);
format = new System.Drawing.StringFormat();
format.Alignment = System.Drawing.StringAlignment.Center;
format.LineAlignment = System.Drawing.StringAlignment.Center;
}
float[,] modulationMatrix = qualityTest.ModulationMatrix;
int matrixHeight = modulationMatrix.GetLength(0);
int matrixWidth = modulationMatrix.GetLength(1);
// create bitmap
System.Drawing.Bitmap result = new System.Drawing.Bitmap(
matrixWidth * cellSize, matrixHeight * cellSize, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
// draw modulation matrix
using (System.Drawing.SolidBrush foreBrush = new System.Drawing.SolidBrush(System.Drawing.Color.White))
{
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(result))
{
for (int y = 0; y < matrixHeight; y++)
{
for (int x = 0; x < matrixWidth; x++)
{
System.Drawing.RectangleF rect = new System.Drawing.RectangleF(x * cellSize, y * cellSize, cellSize, cellSize);
float modulation = modulationMatrix[y, x];
// background
System.Drawing.Brush backBrush = modulation < 0 ? System.Drawing.Brushes.White : System.Drawing.Brushes.Black;
g.FillRectangle(backBrush, rect);
// modulation highlight
foreBrush.Color = System.Drawing.Color.FromArgb(modulationAlpha, GetColor(System.Math.Abs(modulation)));
g.FillRectangle(foreBrush, rect);
if (textFont != null)
{
// modulation percent
string text = System.Math.Round(System.Math.Abs(modulation) * 100).ToString();
System.Drawing.Brush textBrush = modulation >= 0 ? System.Drawing.Brushes.White : System.Drawing.Brushes.Black;
g.DrawString(text, textFont, textBrush, rect, format);
}
}
}
}
}
if (textFont != null)
textFont.Dispose();
return result;
}
/// <summary>
/// Returns the color grade of cell modulation.
/// </summary>
/// <param name="modulation">The cell modulation.</param>
/// <returns>The color.</returns>
private static System.Drawing.Color GetColor(float modulation)
{
System.Drawing.Color hiColor = System.Drawing.Color.FromArgb(0, 192, 0);
float threshold1 = 0.5f;
System.Drawing.Color threshold1Color = System.Drawing.Color.FromArgb(128, 192, 0);
float threshold2 = 0.3f;
System.Drawing.Color threshold2Color = System.Drawing.Color.Orange;
System.Drawing.Color lowColor = System.Drawing.Color.Red;
if (modulation >= threshold1)
return GetInterpolatedColor(threshold1, threshold1Color, 1, hiColor, modulation);
if (modulation >= threshold2)
return GetInterpolatedColor(threshold2, threshold2Color, threshold1, threshold1Color, modulation);
return GetInterpolatedColor(0, lowColor, threshold2, threshold2Color, modulation);
}
/// <summary>
/// Returns the interpolated color for specified value.
/// </summary>
/// <param name="min">The minimum value.</param>
/// <param name="minColor">Color for minimum value.</param>
/// <param name="max">The maximum value.</param>
/// <param name="maxColor">Color for maximum value.</param>
/// <param name="value">The value.</param>
/// <returns>The interpolated color for <i>value</i>.</returns>
private static System.Drawing.Color GetInterpolatedColor(float min, System.Drawing.Color minColor, float max, System.Drawing.Color maxColor, float value)
{
float scale = (value - min) / (max - min);
float r = minColor.R * (1 - scale) + maxColor.R * scale;
float g = minColor.G * (1 - scale) + maxColor.G * scale;
float b = minColor.B * (1 - scale) + maxColor.B * scale;
return System.Drawing.Color.FromArgb((int)System.Math.Round(r), (int)System.Math.Round(g), (int)System.Math.Round(b));
}
}
Target Platforms: .NET 10; .NET 9; .NET 8; .NET 7; .NET 6; .NET Framework 4.8, 4.7, 4.6, 4.5, 4.0, 3.5
ISO15415QualityTest Class
ISO15415QualityTest Members
ModulationGrade
SetQuietZoneSize(BarcodeType,Int32)