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) { var pixel = self.attachAsset('QRCodePixel', { x: x * self.pixelSize, y: y * self.pixelSize, scaleX: self.pixelSize, scaleY: self.pixelSize, tint: 0 }); self.modules[y] = []; self.modules[y][x] = 1; }; self.createPattern = function () { var size = 21; // Standard QR code size self.attachAsset('QRCodePositionL', { x: 0, y: 0 }); self.attachAsset('QRCodePositionR', { x: self.pixelSize * 21, y: 0, anchorX: 1 }); self.attachAsset('QRCodePositionB', { x: 0, y: self.pixelSize * 21, anchorY: 1 }); self.placePixel(8, self.size - 8); // timing pattern for (var i = 8; i <= self.size - 8; i += 2) { self.placePixel(i, 6); self.placePixel(6, i); } var x = size - 1; var y = size - 1; var dir = [-1, 0]; for (var i = 0; i < 6; i++) { if (self.dataCodeWord[i] == 1) { self.placePixel(x, y); } y++; } }; // 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.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: 0xFFFFFF }); /**** * 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
@@ -7,9 +7,10 @@
self.pixelSize = 32;
self.modules = [];
self.string = string;
self.countBitLength = 10;
- self.codeWord = "";
+ self.dataCodeWord = "";
+ self.eccCodeWord = "";
self.size = 21;
// Block = 8 bits
self.maxDataBlock = 19;
self.maxErrorBlock = 7;
@@ -45,55 +46,109 @@
for (var i = 8; i <= self.size - 8; i += 2) {
self.placePixel(i, 6);
self.placePixel(6, i);
}
- // Draw dataCodeWord and eccCodeWord in a zigzag pattern, avoiding position, timing, and format patterns
- // For now, we only have self.codeWord (dataCodeWord), but this is extensible for eccCodeWord
- var size = self.size;
- var codeBits = self.codeWord;
- var bitIndex = 0;
- // Helper to check if a module is reserved (position, timing, format)
- function isReserved(x, y) {
- // Position patterns (top-left, top-right, bottom-left)
- if (x <= 8 && y <= 8 ||
- // top-left
- x >= size - 8 && y <= 8 ||
- // top-right
- x <= 8 && y >= size - 8) {
- // bottom-left
- return true;
+ var x = size - 1;
+ var y = size - 1;
+ var dir = [-1, 0];
+ for (var i = 0; i < 6; i++) {
+ if (self.dataCodeWord[i] == 1) {
+ self.placePixel(x, y);
}
- // Timing patterns (row 6, col 6, except where they overlap position patterns)
- if (y === 6 && x >= 8 && x <= size - 9 || x === 6 && y >= 8 && y <= size - 9) {
- return true;
+ y++;
+ }
+ };
+ // 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;
}
- // Format info (beside position patterns)
- if (y === 8 && x <= 8 || x === 8 && y <= 8) return true; // top-left
- if (y === 8 && x >= size - 8 || x === size - 8 && y <= 8) return true; // top-right
- if (x === 8 && y >= size - 8 || y === size - 8 && x <= 8) return true; // bottom-left
- return false;
+ hexBytes += hexValue + " ";
}
- // Zigzag from bottom-right, two columns at a time, upwards then downwards
- var dir = -1; // -1: up, 1: down
- for (var col = size - 1; col > 0; col -= 2) {
- if (col === 6) col--; // skip vertical timing pattern
- var rowStart = dir === -1 ? size - 1 : 0;
- var rowEnd = dir === -1 ? -1 : size;
- for (var row = rowStart; row !== rowEnd; row += dir) {
- for (var c = 0; c < 2; c++) {
- var x = col - c;
- var y = row;
- if (x < 0 || y < 0 || x >= size || y >= size) continue;
- if (isReserved(x, y)) continue;
- if (bitIndex >= codeBits.length) continue;
- if (codeBits[bitIndex] === "1") {
- self.placePixel(x, y);
- }
- bitIndex++;
+ return hexBytes;
+ };
+ 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;
}
- dir *= -1; // reverse direction
+ 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
@@ -121,26 +176,43 @@
while (binary.length < bitLength) {
binary = "0" + binary;
}
binaryGroups.push(binary);
- console.log("Group '" + groups[j] + "' -> " + num + " -> " + binary + " (" + bitLength + " bits)");
+ console.log("Group " + num + " -> " + binary + " (" + bitLength + " bits)");
}
console.log("Message Binary: " + binaryGroups.join(" ") + " (" + binaryGroups.join("").length + " bits)");
- self.codeWord += "0001";
+ self.dataCodeWord += "0001";
var binary = string.length.toString(2);
// Convert to binary with proper padding
while (binary.length < self.countBitLength) {
binary = "0" + binary;
}
- self.codeWord += binary;
- self.codeWord += binaryGroups.join("");
- self.codeWord += "0000"; // Terminator
- while (self.codeWord.length % 8 != 0) {
- self.codeWord += "0";
+ 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("codeWord: " + self.codeWord + " (" + self.codeWord.length / 8 + " bytes)");
+ 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;
});