bitcoin-atm

bitcoin atm for pyc inc.

git clone https://9o.is/git/bitcoin-atm.git

alignpat.js

(7517B)


      1 /*
      2   Ported to JavaScript by Lazar Laszlo 2011 
      3   
      4   lazarsoft@gmail.com, www.lazarsoft.info
      5   
      6 */
      7 
      8 /*
      9 *
     10 * Copyright 2007 ZXing authors
     11 *
     12 * Licensed under the Apache License, Version 2.0 (the "License");
     13 * you may not use this file except in compliance with the License.
     14 * You may obtain a copy of the License at
     15 *
     16 *      http://www.apache.org/licenses/LICENSE-2.0
     17 *
     18 * Unless required by applicable law or agreed to in writing, software
     19 * distributed under the License is distributed on an "AS IS" BASIS,
     20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     21 * See the License for the specific language governing permissions and
     22 * limitations under the License.
     23 */
     24 
     25 
     26 function AlignmentPattern(posX, posY,  estimatedModuleSize)
     27 {
     28 	this.x=posX;
     29 	this.y=posY;
     30 	this.count = 1;
     31 	this.estimatedModuleSize = estimatedModuleSize;
     32 	
     33 	this.__defineGetter__("EstimatedModuleSize", function()
     34 	{
     35 		return this.estimatedModuleSize;
     36 	}); 
     37 	this.__defineGetter__("Count", function()
     38 	{
     39 		return this.count;
     40 	});
     41 	this.__defineGetter__("X", function()
     42 	{
     43 		return Math.floor(this.x);
     44 	});
     45 	this.__defineGetter__("Y", function()
     46 	{
     47 		return Math.floor(this.y);
     48 	});
     49 	this.incrementCount = function()
     50 	{
     51 		this.count++;
     52 	}
     53 	this.aboutEquals=function( moduleSize,  i,  j)
     54 		{
     55 			if (Math.abs(i - this.y) <= moduleSize && Math.abs(j - this.x) <= moduleSize)
     56 			{
     57 				var moduleSizeDiff = Math.abs(moduleSize - this.estimatedModuleSize);
     58 				return moduleSizeDiff <= 1.0 || moduleSizeDiff / this.estimatedModuleSize <= 1.0;
     59 			}
     60 			return false;
     61 		}
     62 	
     63 }
     64 
     65 function AlignmentPatternFinder( image,  startX,  startY,  width,  height,  moduleSize,  resultPointCallback)
     66 {
     67 	this.image = image;
     68 	this.possibleCenters = new Array();
     69 	this.startX = startX;
     70 	this.startY = startY;
     71 	this.width = width;
     72 	this.height = height;
     73 	this.moduleSize = moduleSize;
     74 	this.crossCheckStateCount = new Array(0,0,0);
     75 	this.resultPointCallback = resultPointCallback;
     76 	
     77 	this.centerFromEnd=function(stateCount,  end)
     78 		{
     79 			return  (end - stateCount[2]) - stateCount[1] / 2.0;
     80 		}
     81 	this.foundPatternCross = function(stateCount)
     82 		{
     83 			var moduleSize = this.moduleSize;
     84 			var maxVariance = moduleSize / 2.0;
     85 			for (var i = 0; i < 3; i++)
     86 			{
     87 				if (Math.abs(moduleSize - stateCount[i]) >= maxVariance)
     88 				{
     89 					return false;
     90 				}
     91 			}
     92 			return true;
     93 		}
     94 
     95 	this.crossCheckVertical=function( startI,  centerJ,  maxCount,  originalStateCountTotal)
     96 		{
     97 			var image = this.image;
     98 			
     99 			var maxI = qrcode.height;
    100 			var stateCount = this.crossCheckStateCount;
    101 			stateCount[0] = 0;
    102 			stateCount[1] = 0;
    103 			stateCount[2] = 0;
    104 			
    105 			// Start counting up from center
    106 			var i = startI;
    107 			while (i >= 0 && image[centerJ + i*qrcode.width] && stateCount[1] <= maxCount)
    108 			{
    109 				stateCount[1]++;
    110 				i--;
    111 			}
    112 			// If already too many modules in this state or ran off the edge:
    113 			if (i < 0 || stateCount[1] > maxCount)
    114 			{
    115 				return NaN;
    116 			}
    117 			while (i >= 0 && !image[centerJ + i*qrcode.width] && stateCount[0] <= maxCount)
    118 			{
    119 				stateCount[0]++;
    120 				i--;
    121 			}
    122 			if (stateCount[0] > maxCount)
    123 			{
    124 				return NaN;
    125 			}
    126 			
    127 			// Now also count down from center
    128 			i = startI + 1;
    129 			while (i < maxI && image[centerJ + i*qrcode.width] && stateCount[1] <= maxCount)
    130 			{
    131 				stateCount[1]++;
    132 				i++;
    133 			}
    134 			if (i == maxI || stateCount[1] > maxCount)
    135 			{
    136 				return NaN;
    137 			}
    138 			while (i < maxI && !image[centerJ + i*qrcode.width] && stateCount[2] <= maxCount)
    139 			{
    140 				stateCount[2]++;
    141 				i++;
    142 			}
    143 			if (stateCount[2] > maxCount)
    144 			{
    145 				return NaN;
    146 			}
    147 			
    148 			var stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
    149 			if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal)
    150 			{
    151 				return NaN;
    152 			}
    153 			
    154 			return this.foundPatternCross(stateCount)?this.centerFromEnd(stateCount, i):NaN;
    155 		}
    156 		
    157 	this.handlePossibleCenter=function( stateCount,  i,  j)
    158 		{
    159 			var stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
    160 			var centerJ = this.centerFromEnd(stateCount, j);
    161 			var centerI = this.crossCheckVertical(i, Math.floor (centerJ), 2 * stateCount[1], stateCountTotal);
    162 			if (!isNaN(centerI))
    163 			{
    164 				var estimatedModuleSize = (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0;
    165 				var max = this.possibleCenters.length;
    166 				for (var index = 0; index < max; index++)
    167 				{
    168 					var center =  this.possibleCenters[index];
    169 					// Look for about the same center and module size:
    170 					if (center.aboutEquals(estimatedModuleSize, centerI, centerJ))
    171 					{
    172 						return new AlignmentPattern(centerJ, centerI, estimatedModuleSize);
    173 					}
    174 				}
    175 				// Hadn't found this before; save it
    176 				var point = new AlignmentPattern(centerJ, centerI, estimatedModuleSize);
    177 				this.possibleCenters.push(point);
    178 				if (this.resultPointCallback != null)
    179 				{
    180 					this.resultPointCallback.foundPossibleResultPoint(point);
    181 				}
    182 			}
    183 			return null;
    184 		}
    185 		
    186 	this.find = function()
    187 	{
    188 			var startX = this.startX;
    189 			var height = this.height;
    190 			var maxJ = startX + width;
    191 			var middleI = startY + (height >> 1);
    192 			// We are looking for black/white/black modules in 1:1:1 ratio;
    193 			// this tracks the number of black/white/black modules seen so far
    194 			var stateCount = new Array(0,0,0);
    195 			for (var iGen = 0; iGen < height; iGen++)
    196 			{
    197 				// Search from middle outwards
    198 				var i = middleI + ((iGen & 0x01) == 0?((iGen + 1) >> 1):- ((iGen + 1) >> 1));
    199 				stateCount[0] = 0;
    200 				stateCount[1] = 0;
    201 				stateCount[2] = 0;
    202 				var j = startX;
    203 				// Burn off leading white pixels before anything else; if we start in the middle of
    204 				// a white run, it doesn't make sense to count its length, since we don't know if the
    205 				// white run continued to the left of the start point
    206 				while (j < maxJ && !image[j + qrcode.width* i])
    207 				{
    208 					j++;
    209 				}
    210 				var currentState = 0;
    211 				while (j < maxJ)
    212 				{
    213 					if (image[j + i*qrcode.width])
    214 					{
    215 						// Black pixel
    216 						if (currentState == 1)
    217 						{
    218 							// Counting black pixels
    219 							stateCount[currentState]++;
    220 						}
    221 						else
    222 						{
    223 							// Counting white pixels
    224 							if (currentState == 2)
    225 							{
    226 								// A winner?
    227 								if (this.foundPatternCross(stateCount))
    228 								{
    229 									// Yes
    230 									var confirmed = this.handlePossibleCenter(stateCount, i, j);
    231 									if (confirmed != null)
    232 									{
    233 										return confirmed;
    234 									}
    235 								}
    236 								stateCount[0] = stateCount[2];
    237 								stateCount[1] = 1;
    238 								stateCount[2] = 0;
    239 								currentState = 1;
    240 							}
    241 							else
    242 							{
    243 								stateCount[++currentState]++;
    244 							}
    245 						}
    246 					}
    247 					else
    248 					{
    249 						// White pixel
    250 						if (currentState == 1)
    251 						{
    252 							// Counting black pixels
    253 							currentState++;
    254 						}
    255 						stateCount[currentState]++;
    256 					}
    257 					j++;
    258 				}
    259 				if (this.foundPatternCross(stateCount))
    260 				{
    261 					var confirmed = this.handlePossibleCenter(stateCount, i, maxJ);
    262 					if (confirmed != null)
    263 					{
    264 						return confirmed;
    265 					}
    266 				}
    267 			}
    268 			
    269 			// Hmm, nothing we saw was observed and confirmed twice. If we had
    270 			// any guess at all, return it.
    271 			if (!(this.possibleCenters.length == 0))
    272 			{
    273 				return  this.possibleCenters[0];
    274 			}
    275 			
    276 			throw "Couldn't find enough alignment patterns";
    277 		}
    278 	
    279 }