encodeData static method
Encodes the given binary content as an Aztec symbol
@param data input data string @param minECCPercent minimal percentage of error check words (According to ISO/IEC 24778:2008, a minimum of 23% + 3 words is recommended) @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers @param charset character set to mark using ECI; if null, no ECI code will be inserted, and the default encoding of ISO/IEC 8859-1 will be assuming by readers. @return Aztec symbol matrix with metadata
Implementation
static AztecCode encodeData(
Uint8List data, [
int minECCPercent = defaultAztecLayers,
int userSpecifiedLayers = defaultAztecLayers,
Encoding? charset,
]) {
// High-level encode
final BitArray bits = HighLevelEncoder(data, charset).encode();
// stuff bits and choose symbol size
final int eccBits = bits.size * minECCPercent ~/ 100 + 11;
final int totalSizeBits = bits.size + eccBits;
bool compact;
int layers;
int totalBitsLayer;
int wordSize;
BitArray? stuffedBits;
if (userSpecifiedLayers != defaultAztecLayers) {
compact = userSpecifiedLayers < 0;
layers = (userSpecifiedLayers).abs();
if (layers > (compact ? _maxNbBitsCompact : _maxNbBits)) {
throw ArgumentError('Illegal value $userSpecifiedLayers for layers');
}
totalBitsLayer = _totalBitsInLayer(layers, compact);
wordSize = _wordSize[layers];
final int usableBitsInLayers =
totalBitsLayer - (totalBitsLayer % wordSize);
stuffedBits = stuffBits(bits, wordSize);
if (stuffedBits.size + eccBits > usableBitsInLayers) {
throw ArgumentError('Data to large for user specified layer');
}
if (compact && stuffedBits.size > wordSize * 64) {
// Compact format only allows 64 data words, though C4 can hold more words than that
throw ArgumentError('Data to large for user specified layer');
}
} else {
wordSize = 0;
stuffedBits = null;
// We look at the possible table sizes in the order Compact1, Compact2, Compact3,
// Compact4, Normal4,... Normal(i) for i < 4 isn't typically used since Compact(i+1)
// is the same size, but has more data.
for (int i = 0;; i++) {
if (i > _maxNbBits) {
throw ArgumentError('Data too large for an Aztec code');
}
compact = i <= 3;
layers = compact ? i + 1 : i;
totalBitsLayer = _totalBitsInLayer(layers, compact);
if (totalSizeBits > totalBitsLayer) {
continue;
}
// [Re]stuff the bits if this is the first opportunity, or if the
// wordSize has changed
if (stuffedBits == null || wordSize != _wordSize[layers]) {
wordSize = _wordSize[layers];
stuffedBits = stuffBits(bits, wordSize);
}
final int usableBitsInLayers =
totalBitsLayer - (totalBitsLayer % wordSize);
if (compact && stuffedBits.size > wordSize * 64) {
// Compact format only allows 64 data words, though C4 can hold more words than that
continue;
}
if (stuffedBits.size + eccBits <= usableBitsInLayers) {
break;
}
}
}
final BitArray messageBits =
_generateCheckWords(stuffedBits, totalBitsLayer, wordSize);
// generate mode message
final int messageSizeInWords = stuffedBits.size ~/ wordSize;
final BitArray modeMessage =
generateModeMessage(compact, layers, messageSizeInWords);
// allocate symbol
final int baseMatrixSize =
(compact ? 11 : 14) + layers * 4; // not including alignment lines
final List<int> alignmentMap = List.filled(baseMatrixSize, 0);
int matrixSize;
if (compact) {
// no alignment marks in compact mode, alignmentMap is a no-op
matrixSize = baseMatrixSize;
for (int i = 0; i < alignmentMap.length; i++) {
alignmentMap[i] = i;
}
} else {
matrixSize = baseMatrixSize + 1 + 2 * ((baseMatrixSize ~/ 2 - 1) ~/ 15);
final int origCenter = baseMatrixSize ~/ 2;
final int center = matrixSize ~/ 2;
for (int i = 0; i < origCenter; i++) {
final int newOffset = i + i ~/ 15;
alignmentMap[origCenter - i - 1] = center - newOffset - 1;
alignmentMap[origCenter + i] = center + newOffset + 1;
}
}
final BitMatrix matrix = BitMatrix(matrixSize);
// draw data bits
for (int i = 0, rowOffset = 0; i < layers; i++) {
final int rowSize = (layers - i) * 4 + (compact ? 9 : 12);
for (int j = 0; j < rowSize; j++) {
final int columnOffset = j * 2;
for (int k = 0; k < 2; k++) {
if (messageBits.get(rowOffset + columnOffset + k)) {
matrix.set(alignmentMap[i * 2 + k], alignmentMap[i * 2 + j]);
}
if (messageBits.get(rowOffset + rowSize * 2 + columnOffset + k)) {
matrix.set(
alignmentMap[i * 2 + j],
alignmentMap[baseMatrixSize - 1 - i * 2 - k],
);
}
if (messageBits.get(rowOffset + rowSize * 4 + columnOffset + k)) {
matrix.set(
alignmentMap[baseMatrixSize - 1 - i * 2 - k],
alignmentMap[baseMatrixSize - 1 - i * 2 - j],
);
}
if (messageBits.get(rowOffset + rowSize * 6 + columnOffset + k)) {
matrix.set(
alignmentMap[baseMatrixSize - 1 - i * 2 - j],
alignmentMap[i * 2 + k],
);
}
}
}
rowOffset += rowSize * 8;
}
// draw mode message
_drawModeMessage(matrix, compact, matrixSize, modeMessage);
// draw alignment marks
if (compact) {
_drawBullsEye(matrix, matrixSize ~/ 2, 5);
} else {
_drawBullsEye(matrix, matrixSize ~/ 2, 7);
for (int i = 0, j = 0; i < baseMatrixSize / 2 - 1; i += 15, j += 16) {
for (int k = (matrixSize ~/ 2) & 1; k < matrixSize; k += 2) {
matrix.set(matrixSize ~/ 2 - j, k);
matrix.set(matrixSize ~/ 2 + j, k);
matrix.set(k, matrixSize ~/ 2 - j);
matrix.set(k, matrixSize ~/ 2 + j);
}
}
}
return AztecCode(
isCompact: compact,
size: matrixSize,
layers: layers,
codeWords: messageSizeInWords,
matrix: matrix,
);
}