diff --git a/finder-example.html b/finder-example.html new file mode 100644 index 0000000..e53731a --- /dev/null +++ b/finder-example.html @@ -0,0 +1,61 @@ + + + + QR Code Finder Example + + + + + + + + + + diff --git a/index2.html b/index2.html new file mode 100644 index 0000000..d7676cf --- /dev/null +++ b/index2.html @@ -0,0 +1,61 @@ + + + + QR Code Display + + + + + + + + + + diff --git a/js/main.js b/js/main.js index 412d66b..2de983e 100644 --- a/js/main.js +++ b/js/main.js @@ -6,7 +6,7 @@ **************************************** */ -var APP_VERSION = '0.3.3'; +var APP_VERSION = '0.4.0'; var qr_version = 1; //Current QR version (1-9) var qr_pixel_size = 10; //Current view size of QR code (pixel per module) @@ -33,6 +33,9 @@ var is_data_module = []; //Store data that separate between data module a var history_array = []; //Store history information and its qr_array data var active_history = -1; //Current active history +const maxSupportedSize = 100; +const maxVersion = 50; + /*** * * generate QR table based on qr_array @@ -571,7 +574,7 @@ function importFromImage(src, cb){ var qrArray = qRCodeMatrix.bits.bits; var size = qRCodeMatrix.bits.width; - if(size > 53){ + if(size > maxSupportedSize){ alert("QR version is unsupported"); return; } @@ -1462,7 +1465,7 @@ $(document).ready(function(){ $("#btn-version-plus").click(function(){ if(changed_state){ if(confirm("Are you sure want to proceed?\nYour unsaved progress will be lost!")){ - if(qr_version != 9){ + if(qr_version != maxVersion){ qr_version += 1; qr_size = 17+(qr_version*4); $("#qr-version").val(qr_size+"x"+qr_size+" (ver. "+qr_version+")"); @@ -1470,7 +1473,7 @@ $(document).ready(function(){ } } } else { - if(qr_version != 9){ + if(qr_version != maxVersion){ qr_version += 1; qr_size = 17+(qr_version*4); $("#qr-version").val(qr_size+"x"+qr_size+" (ver. "+qr_version+")"); diff --git a/js/qr.js b/js/qr.js new file mode 100644 index 0000000..e658ee6 --- /dev/null +++ b/js/qr.js @@ -0,0 +1,197 @@ +const WHITE_COLOR = 0; +const BLACK_COLOR = 1; +const RED_COLOR = 3; +const GREY_COLOR = -1; + +/* + A finder is defined by 3 squares: + - A black 7x7 square + - A white 5x5 square + - A black 3x3 square + + Padding is denoted by a 9x9 square surrounding the element + and being cropped on its corners. + + x and y denote the (x,y) coordinate of the 7x7 square, taken + at the top left corner +*/ + +function draw_square(t, x, y, size, color){ + for(let i=x; i= t.length || i < 0){ + continue + } + if(j >= t.length || j < 0) { + continue + } + t[i][j] = color; + } + } +} + +function generate_finder_separator(t, x, y) { + return draw_square(t, x - 1, y - 1, 9, WHITE_COLOR); +} + +function generate_finder(t, x, y){ + generate_finder_separator(t, x, y); + draw_square(t, x, y, 7, BLACK_COLOR); + draw_square(t, x + 1, y + 1, 5, WHITE_COLOR); + draw_square(t, x + 2, y + 2, 3, BLACK_COLOR); +} + +/* + The timing patterns is a pattern of black / white squares (1x1) that + begin with a black one and move either horizontally or vertically, + connecting the finders separators. +*/ +function generate_timing_pattern_v(t, xStart, yStart, yEnd){ + // Start with black + let current = BLACK_COLOR; + for(let j=yStart; j<=yEnd; j++){ + t[xStart][j] = current; + current = (current == BLACK_COLOR ? WHITE_COLOR : BLACK_COLOR) + } +} + +function generate_timing_pattern_h(t, xStart, yStart, xEnd){ + // Start with black + let current = BLACK_COLOR; + for(let i=xStart; i<=xEnd; i++){ + t[i][yStart] = current; + current = (current == BLACK_COLOR ? WHITE_COLOR : BLACK_COLOR) + } +} + + +let versions = []; +for(let i=0;i<40;i++){ + versions.push( + [21 + i*4, 21 + i*4] + ) +} + +let alignment_lookup = [ + [], + [6, 18], + [6, 22], + [6, 26], + [6, 30], + [6, 34], + [6, 22, 38], + [6, 24, 42], + [6, 26, 46], + [6, 28, 50], + [6, 30, 54], + [6, 32, 58], + [6, 34, 62], + [6, 26, 46, 66], + [6, 26, 48, 70], + [6, 26, 50, 74], + [6, 30, 54, 78], + [6, 30, 56, 82], + [6, 30, 58, 86], + [6, 34, 62, 90], + [6, 28, 50, 72, 94], + [6, 26, 50, 74, 98], + [6, 30, 54, 78, 102], + [6, 28, 54, 80, 106], + [6, 32, 58, 84, 110], + [6, 30, 58, 86, 114], + [6, 34, 62, 90, 118], + [6, 26, 50, 74, 98, 122], + [6, 30, 54, 78, 102, 126], + [6, 26, 52, 78, 104, 130], + [6, 30, 56, 82, 108, 134], + [6, 34, 60, 86, 112, 138], + [6, 30, 58, 86, 114, 142], + [6, 34, 62, 90, 118, 146], + [6, 30, 54, 78, 102, 126, 150], + [6, 24, 50, 76, 102, 128, 154], + [6, 28, 54, 80, 106, 132, 158], + [6, 32, 58, 84, 110, 136, 162], + [6, 26, 54, 82, 110, 138, 166], + [6, 30, 58, 86, 114, 142, 170] +]; + +/* + Alignment patterns are boxes sized 5x5 that are + formed as follows: + + - Outer 5x5 black square + - Inner 3x3 white square + - Inner-most 1x1 black square + + The coordinates from alignment_lookup refer to the center + of the alignment pattern (the 1x1 square). +*/ + +function add_alignment_patterns(t, index){ + let alignment = alignment_lookup[index]; + if(alignment.length == 0){ + return; + } + + let alignment_locs = []; + + for(let i=0; i t.length - 8 && t_y < 8) { + continue + } + + if(l_x < 8 && t_y < 8) { + continue; + } + + if(l_x < 8 && b_y > t.length - 8){ + continue + } + + draw_square(t, x-2, y-2, 5, BLACK_COLOR); + draw_square(t, x-1, y-1, 3, WHITE_COLOR); + draw_square(t, x, y, 1, BLACK_COLOR); + + + } + console.log(alignment_locs); +} + +function generate_qr(version){ + console.log(`Generating ${version}`) + let t = []; + let sizes = versions[version-1]; + let x_max = sizes[0]; + let y_max = sizes[1]; + + for(let i = 0; i