Code edit (2 edits merged)
Please save this source code
User prompt
Draw the format bits after drawDataCodewords, error correction level 'L', mask pattern 2
User prompt
Draw the format bits after drawDataCodewords, error correction level 'L', mask pattern 111
Code edit (2 edits merged)
Please save this source code
User prompt
Draw the format bits after drawDataCodewords, error correction level 'L', mask pattern 0b111
User prompt
Draw the format bits after drawDataCodewords
Code edit (11 edits merged)
Please save this source code
User prompt
Draw the data and ecc codeWord in a zigzag pattern in the QR code, If there is already a module in place, skip until that isn't a module in place.
Code edit (3 edits merged)
Please save this source code
User prompt
make the `placePixel` function return if the x or y coordinates are out of bounds
Code edit (1 edits merged)
Please save this source code
User prompt
Draw the white pixel for the patterns
Code edit (4 edits merged)
Please save this source code
User prompt
Rewrite the pattern drawing function for the new parameters in `placePixel`
User prompt
Rewrite the pattern drawing function for the new parameters.
Code edit (3 edits merged)
Please save this source code
User prompt
Remove the position patterns and redraw them, also write all the pixel into a array before for printing it to the screen
Code edit (9 edits merged)
Please save this source code
User prompt
Remove the position patterns and redraw them
Code edit (1 edits merged)
Please save this source code
User prompt
Draw `dataCodeWord` and `eccCodeWord` in a zigzag pattern, avoiding the position pattern, timing pattern and format bits.
User prompt
Draw `dataCodeWord` and `eccCodeWord` in a zigzag pattern, avoiding the position pattern.
Code edit (1 edits merged)
Please save this source code
Code edit (10 edits merged)
Please save this source code
User prompt
In the `QRcode.encodeECC` method, compute the error correction code from `self.dataCodeWord`, and put the ECC into `self.eccCodeWord`
/****
* Classes
****/
var QRCode = Container.expand(function (string) {
var self = Container.call(this);
// Initialize QR code properties
self.pixelSize = 32;
self.modules = [];
self.string = string;
self.countBitLength = 10;
self.dataCodeWord = "";
self.eccCodeWord = "";
self.size = 21;
// Block = 8 bits
self.maxDataBlock = 19;
self.maxErrorBlock = 7;
self.placePixel = function (x, y, isBlack) {
if (x < 0 || x >= self.size || y < 0 || y >= self.size) {
return;
}
// Initialize row if it doesn't exist
if (!self.modules[y]) {
self.modules[y] = [];
}
// Mark pixel in modules array
self.modules[y][x] = isBlack;
};
self.drawPositionPattern = function (centerX, centerY) {
// Draw 8x8 position pattern
for (var y = -4; y <= 4; y++) {
for (var x = -4; x <= 4; x++) {
var absX = Math.abs(x);
var absY = Math.abs(y);
// Separator
if (absX === 4 || absY === 4) {
self.placePixel(centerX + x, centerY + y, false);
} else if (absX === 3 || absY === 3 || absX <= 1 && absY <= 1) {
// Outer black ring, white ring, inner black square
self.placePixel(centerX + x, centerY + y, true);
} else if (absX === 2 || absY === 2) {
// White middle ring
self.placePixel(centerX + x, centerY + y, false);
}
}
}
};
self.drawToScreen = function () {
// Draw all pixels from modules array
for (var y = 0; y < self.size; y++) {
if (self.modules[y]) {
for (var x = 0; x < self.size; x++) {
if (self.modules[y][x] !== undefined) {
var pixel = self.attachAsset('QRCodePixel', {
x: x * self.pixelSize,
y: y * self.pixelSize,
scaleX: self.pixelSize,
scaleY: self.pixelSize,
tint: self.modules[y][x] ? 0 : 0xFFFFFF
});
}
}
}
}
};
self.createPattern = function () {
// Draw position patterns at three corners
self.drawPositionPattern(3, 3); // Top-left
self.drawPositionPattern(self.size - 4, 3); // Top-right
self.drawPositionPattern(3, self.size - 4); // Bottom-left
// timing pattern
for (var i = 8; i <= self.size - 9; i++) {
self.placePixel(i, 6, i % 2 == 0);
self.placePixel(6, i, i % 2 == 0);
}
// Dark module
self.placePixel(8, self.size - 8, true);
// Draw data and ECC codewords in zigzag pattern
self.drawDataCodewords();
// Format information
self.drawFormatInformation();
self.drawToScreen();
};
// Convert to hexadecimal and split into bytes
self.binToHex = function (bin) {
var hexBytes = "";
for (var i = 0; i < bin.length; i += 8) {
var _byte = bin.substr(i, 8);
var hexValue = parseInt(_byte, 2).toString(16).toUpperCase();
if (hexValue.length === 1) {
hexValue = "0" + hexValue;
}
hexBytes += hexValue + " ";
}
return hexBytes;
};
self.drawDataCodewords = function () {
var allCodewords = self.dataCodeWord + self.eccCodeWord;
var bitIndex = 0;
var direction = -1; // -1 for up, 1 for down
// Start from the right side, moving in pairs of columns
for (var rightCol = self.size - 1; rightCol > 0; rightCol -= 2) {
// Skip the timing column
if (rightCol === 6) {
rightCol = 5;
}
// Process the entire height
for (var vert = 0; vert < self.size; vert++) {
for (var c = 0; c < 2; c++) {
var col = rightCol - c;
var row = direction === -1 ? self.size - 1 - vert : vert;
// Check if we've placed all bits
if (bitIndex >= allCodewords.length) {
return;
}
// Check if this position is already occupied
if (self.modules[row] && self.modules[row][col] !== undefined) {
continue; // Skip this position
}
// Place the bit
var bit = allCodewords[bitIndex] === '1';
// Mask Pattern 7 (111)
if (((row + col) % 2 + row * col % 3) % 2 == 0) {
bit = !bit;
}
self.placePixel(col, row, bit);
bitIndex++;
}
}
// Change direction for next column pair
direction = -direction;
}
};
self.drawFormatInformation = function () {
// Final format string for ECC Level L (01) and Mask 7 (111)
// is 110101000110111 after XORing with mask 101010000010010
var formatString = "110101000110111";
// Place format info around top-left position pattern
var bitIndex = 0;
// Vertical part
for (var y = 0; y <= 8; y++) {
if (y === 6) continue;
self.placePixel(8, y, formatString[bitIndex++] === '1');
}
// Horizontal part
for (var x = 7; x >= 0; x--) {
if (x === 6) continue;
self.placePixel(x, 8, formatString[bitIndex++] === '1');
}
// Place format info near other two corners
bitIndex = 0;
// Top-right horizontal part
for (var x = self.size - 1; x >= self.size - 8; x--) {
self.placePixel(x, 8, formatString[bitIndex++] === '1');
}
// Bottom-left vertical part
for (var y = self.size - 7; y < self.size; y++) {
self.placePixel(8, y, formatString[bitIndex++] === '1');
}
};
self.encodeECC = function () {
var LOG_TABLE = new Array(256);
var EXP_TABLE = new Array(256);
var p = 1;
for (var i = 0; i < 255; i++) {
EXP_TABLE[i] = p;
LOG_TABLE[p] = i;
p = p << 1;
if (p > 255) {
p = p ^ 285;
}
}
EXP_TABLE[255] = 1;
var gf_multiply = function gf_multiply(a, b) {
if (a === 0 || b === 0) {
return 0;
}
return EXP_TABLE[(LOG_TABLE[a] + LOG_TABLE[b]) % 255];
};
var getGeneratorPolynomial = function getGeneratorPolynomial(numEccBytes) {
var g = [1];
for (var i = 0; i < numEccBytes; i++) {
var next_g = new Array(g.length + 1);
for (var k = 0; k < next_g.length; k++) {
next_g[k] = 0;
}
var alpha_pow_i = EXP_TABLE[i];
for (var j = 0; j < g.length; j++) {
next_g[j] = g[j];
}
for (var j = 0; j < g.length; j++) {
next_g[j + 1] ^= gf_multiply(g[j], alpha_pow_i);
}
g = next_g;
}
return g;
};
// 1. Convert dataCodeWord to bytes
var dataBytes = [];
for (var i = 0; i < self.dataCodeWord.length; i += 8) {
var byteString = self.dataCodeWord.substr(i, 8);
dataBytes.push(parseInt(byteString, 2));
}
// 2. Get generator polynomial
var generator = getGeneratorPolynomial(self.maxErrorBlock);
// 3. Perform polynomial division to get ECC
var dataLen = dataBytes.length;
var eccLen = self.maxErrorBlock;
var msg_out = new Array(dataLen + eccLen);
for (var i = 0; i < msg_out.length; i++) {
msg_out[i] = 0;
}
for (var i = 0; i < dataLen; i++) {
msg_out[i] = dataBytes[i];
}
for (var i = 0; i < dataLen; i++) {
var coef = msg_out[i];
if (coef !== 0) {
for (var j = 0; j < generator.length; j++) {
msg_out[i + j] ^= gf_multiply(generator[j], coef);
}
}
}
var eccBytes = [];
for (var i = 0; i < eccLen; i++) {
eccBytes.push(msg_out[dataLen + i]);
}
// 4. Convert ECC bytes to binary string
var eccBinaryString = "";
for (var i = 0; i < eccBytes.length; i++) {
var binary = eccBytes[i].toString(2);
while (binary.length < 8) {
binary = "0" + binary;
}
eccBinaryString += binary;
}
self.eccCodeWord = eccBinaryString;
console.log("eccCodeWord: " + self.binToHex(self.eccCodeWord));
};
// Encode numeric data method
self.encodeNumeric = function () {
// Split into groups of 3 digits
var groups = [];
for (var i = 0; i < self.string.length; i += 3) {
var group = self.string.substr(i, Math.min(3, self.string.length - i));
groups.push(group);
}
console.log("Groups of 3: " + groups.join(", "));
// Convert each group to binary
var binaryGroups = [];
for (var j = 0; j < groups.length; j++) {
var num = parseInt(groups[j], 10);
var bitLength;
// Determine bit length based on group size
if (groups[j].length === 3) {
bitLength = 10; // 3 digits need 10 bits (0-999)
} else if (groups[j].length === 2) {
bitLength = 7; // 2 digits need 7 bits (0-99)
} else {
bitLength = 4; // 1 digit needs 4 bits (0-9)
}
// Convert to binary with proper padding
var binary = num.toString(2);
while (binary.length < bitLength) {
binary = "0" + binary;
}
binaryGroups.push(binary);
console.log("Group " + num + " -> " + binary + " (" + bitLength + " bits)");
}
console.log("Message Binary: " + binaryGroups.join(" ") + " (" + binaryGroups.join("").length + " bits)");
self.dataCodeWord += "0001";
var binary = string.length.toString(2);
// Convert to binary with proper padding
while (binary.length < self.countBitLength) {
binary = "0" + binary;
}
self.dataCodeWord += binary;
self.dataCodeWord += binaryGroups.join("");
self.dataCodeWord += "0000"; // Terminator
// Add byte padding
var currentBytes = self.dataCodeWord.length / 8;
var bytesNeeded = self.maxDataBlock - currentBytes;
// Pad to byte boundary first
var bitsToNextByte = self.dataCodeWord.length % 8;
if (bitsToNextByte > 0) {
var padBits = 8 - bitsToNextByte;
for (var p = 0; p < padBits; p++) {
self.dataCodeWord += "0";
}
}
console.log("dataCodeWord: " + self.dataCodeWord + " (" + self.dataCodeWord.length / 8 + " bytes)");
// Add alternating padding bytes (11101100 and 00010001)
var paddingBytes = ["11101100", "00010001"];
var paddingIndex = 0;
while (self.dataCodeWord.length / 8 < self.maxDataBlock) {
self.dataCodeWord += paddingBytes[paddingIndex];
paddingIndex = (paddingIndex + 1) % 2;
}
console.log("dataCodeWord with padding: " + self.binToHex(self.dataCodeWord));
};
self.encodeNumeric();
self.encodeECC();
self.createPattern();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xAAAAAA
});
/****
* Game Code
****/
// Create QR code container
var qrCode = new QRCode("8675309");
qrCode.x = (2048 - qrCode.width) / 2;
qrCode.y = (2732 - qrCode.height) / 2;
game.addChild(qrCode); ===================================================================
--- original.js
+++ change.js
@@ -66,27 +66,19 @@
// Draw position patterns at three corners
self.drawPositionPattern(3, 3); // Top-left
self.drawPositionPattern(self.size - 4, 3); // Top-right
self.drawPositionPattern(3, self.size - 4); // Bottom-left
- // Temporary Dummy Format Bits
- for (var i = self.size - 8; i <= self.size; i++) {
- self.placePixel(i, 8, false);
- self.placePixel(8, i, false);
- }
- for (var i = 0; i <= 8; i++) {
- self.placePixel(i, 8, false);
- self.placePixel(8, i, false);
- }
- self.placePixel(8, self.size - 8, true);
// timing pattern
for (var i = 8; i <= self.size - 9; i++) {
self.placePixel(i, 6, i % 2 == 0);
self.placePixel(6, i, i % 2 == 0);
}
+ // Dark module
+ self.placePixel(8, self.size - 8, true);
// Draw data and ECC codewords in zigzag pattern
self.drawDataCodewords();
- // Draw format bits
- // self.drawFormatBits();
+ // Format information
+ self.drawFormatInformation();
self.drawToScreen();
};
// Convert to hexadecimal and split into bytes
self.binToHex = function (bin) {
@@ -100,55 +92,8 @@
hexBytes += hexValue + " ";
}
return hexBytes;
};
- self.drawFormatBits = function () {
- // Format string for error correction level L (01) and mask pattern 111 (0b111)
- // Format = error correction (2 bits) + mask pattern (3 bits) = 01111
- var formatBits = "01111";
- // BCH error correction for format information
- // Generator polynomial: x^10 + x^8 + x^5 + x^4 + x^2 + x + 1 = 10100110111
- var generator = 0x537; // 10100110111 in binary
- // Shift format bits left by 10 positions for BCH calculation
- var format = parseInt(formatBits, 2) << 10;
- // Calculate BCH code
- var remainder = format;
- for (var i = 14; i >= 10; i--) {
- if (remainder >> i & 1) {
- remainder ^= generator << i - 10;
- }
- }
- // Combine format bits with BCH code
- format = parseInt(formatBits, 2) << 10 | remainder;
- // XOR with mask pattern 101010000010010
- var maskPattern = 0x5412; // 101010000010010 in binary
- format ^= maskPattern;
- // Convert to 15-bit binary string
- var formatString = format.toString(2);
- while (formatString.length < 15) {
- formatString = "0" + formatString;
- }
- // Draw format bits around top-left position pattern
- for (var i = 0; i < 6; i++) {
- self.placePixel(i, 8, formatString[i] === '1');
- }
- self.placePixel(7, 8, formatString[6] === '1');
- self.placePixel(8, 8, formatString[7] === '1');
- self.placePixel(8, 7, formatString[8] === '1');
- for (var i = 9; i < 15; i++) {
- self.placePixel(8, 14 - i, formatString[i] === '1');
- }
- // Draw format bits around top-right and bottom-left patterns
- var index = 0;
- for (var i = self.size - 1; i >= self.size - 7; i--) {
- self.placePixel(i, 8, formatString[index] === '1');
- index++;
- }
- for (var i = self.size - 8; i >= 0; i--) {
- self.placePixel(8, i, formatString[index] === '1');
- index++;
- }
- };
self.drawDataCodewords = function () {
var allCodewords = self.dataCodeWord + self.eccCodeWord;
var bitIndex = 0;
var direction = -1; // -1 for up, 1 for down
@@ -172,10 +117,10 @@
continue; // Skip this position
}
// Place the bit
var bit = allCodewords[bitIndex] === '1';
- // Mask Pattern 2
- if (col % 3 == 0) {
+ // Mask Pattern 7 (111)
+ if (((row + col) % 2 + row * col % 3) % 2 == 0) {
bit = !bit;
}
self.placePixel(col, row, bit);
bitIndex++;
@@ -184,8 +129,35 @@
// Change direction for next column pair
direction = -direction;
}
};
+ self.drawFormatInformation = function () {
+ // Final format string for ECC Level L (01) and Mask 7 (111)
+ // is 110101000110111 after XORing with mask 101010000010010
+ var formatString = "110101000110111";
+ // Place format info around top-left position pattern
+ var bitIndex = 0;
+ // Vertical part
+ for (var y = 0; y <= 8; y++) {
+ if (y === 6) continue;
+ self.placePixel(8, y, formatString[bitIndex++] === '1');
+ }
+ // Horizontal part
+ for (var x = 7; x >= 0; x--) {
+ if (x === 6) continue;
+ self.placePixel(x, 8, formatString[bitIndex++] === '1');
+ }
+ // Place format info near other two corners
+ bitIndex = 0;
+ // Top-right horizontal part
+ for (var x = self.size - 1; x >= self.size - 8; x--) {
+ self.placePixel(x, 8, formatString[bitIndex++] === '1');
+ }
+ // Bottom-left vertical part
+ for (var y = self.size - 7; y < self.size; y++) {
+ self.placePixel(8, y, formatString[bitIndex++] === '1');
+ }
+ };
self.encodeECC = function () {
var LOG_TABLE = new Array(256);
var EXP_TABLE = new Array(256);
var p = 1;