/** * <p>When QR Codes use multiple data blocks, they are actually interleaved. * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This * method will separate the data into original blocks.</p> * * @param rawCodewords bytes as read directly from the QR Code * @param version version of the QR Code * @param ecLevel error-correction level of the QR Code * @return DataBlocks containing original bytes, "de-interleaved" from representation in the * QR Code */ static function getDataBlocks($rawCodewords, $version, $ecLevel) { if (count($rawCodewords) != $version->getTotalCodewords()) { throw new \InvalidArgumentException(); } // Figure out the number and size of data blocks used by this version and // error correction level $ecBlocks = $version->getECBlocksForLevel($ecLevel); // First count the total number of data blocks $totalBlocks = 0; $ecBlockArray = $ecBlocks->getECBlocks(); foreach ($ecBlockArray as $ecBlock) { $totalBlocks += $ecBlock->getCount(); } // Now establish DataBlocks of the appropriate size and number of data codewords $result = array(); //new DataBlock[$totalBlocks]; $numResultBlocks = 0; foreach ($ecBlockArray as $ecBlock) { for ($i = 0; $i < $ecBlock->getCount(); $i++) { $numDataCodewords = $ecBlock->getDataCodewords(); $numBlockCodewords = $ecBlocks->getECCodewordsPerBlock() + $numDataCodewords; $result[$numResultBlocks++] = new DataBlock($numDataCodewords, fill_array(0, $numBlockCodewords, 0)); } } // All blocks have the same amount of data, except that the last n // (where n may be 0) have 1 more byte. Figure out where these start. $shorterBlocksTotalCodewords = count($result[0]->codewords); $longerBlocksStartAt = count($result) - 1; while ($longerBlocksStartAt >= 0) { $numCodewords = count($result[$longerBlocksStartAt]->codewords); if ($numCodewords == $shorterBlocksTotalCodewords) { break; } $longerBlocksStartAt--; } $longerBlocksStartAt++; $shorterBlocksNumDataCodewords = $shorterBlocksTotalCodewords - $ecBlocks->getECCodewordsPerBlock(); // The last elements of result may be 1 element longer; // first fill out as many elements as all of them have $rawCodewordsOffset = 0; for ($i = 0; $i < $shorterBlocksNumDataCodewords; $i++) { for ($j = 0; $j < $numResultBlocks; $j++) { $result[$j]->codewords[$i] = $rawCodewords[$rawCodewordsOffset++]; } } // Fill out the last data block in the longer ones for ($j = $longerBlocksStartAt; $j < $numResultBlocks; $j++) { $result[$j]->codewords[$shorterBlocksNumDataCodewords] = $rawCodewords[$rawCodewordsOffset++]; } // Now add in error correction blocks $max = count($result[0]->codewords); for ($i = $shorterBlocksNumDataCodewords; $i < $max; $i++) { for ($j = 0; $j < $numResultBlocks; $j++) { $iOffset = $j < $longerBlocksStartAt ? $i : $i + 1; $result[$j]->codewords[$iOffset] = $rawCodewords[$rawCodewordsOffset++]; } } return $result; }
/** * <p>Creates a finder that will search the image for three finder patterns.</p> * * @param image image to search */ public function __construct($image, $resultPointCallback = null) { $this->image = $image; $this->possibleCenters = array(); //new ArrayList<>(); $this->crossCheckStateCount = fill_array(0, 5, 0); $this->resultPointCallback = $resultPointCallback; }
public function __construct($source) { self::$LUMINANCE_SHIFT = 8 - self::$LUMINANCE_BITS; self::$LUMINANCE_BUCKETS = 1 << self::$LUMINANCE_BITS; parent::__construct($source); $this->luminances = self::$EMPTY; $this->buckets = fill_array(0, self::$LUMINANCE_BUCKETS, 0); $this->source = $source; }
public function __construct($width, $height = false, $rowSize = false, $bits = false) { if (!$height) { $height = $width; } if (!$rowSize) { $rowSize = intval(($width + 31) / 32); } if (!$bits) { $bits = fill_array(0, $rowSize * $height, 0); array(); //new int[rowSize * height]; } $this->width = $width; $this->height = $height; $this->rowSize = $rowSize; $this->bits = $bits; }
function cron_fill_array($niz, $opseg) { $rezultat = $niz; if (strstr($opseg, ",")) { foreach (explode(",", $opseg) as $element) { $rezultat = fill_array($rezultat, $element); } } else { if (strstr($opseg, "-")) { list($a, $b) = explode("-", $opseg); for ($i = $a; $i <= $b; $i++) { $rezultat[] = $i; } } else { $rezultat[] = $opseg; } } return $rezultat; }
public function sampleGrid_($image, $dimensionX, $dimensionY, $transform) { if ($dimensionX <= 0 || $dimensionY <= 0) { throw NotFoundException::getNotFoundInstance(); } $bits = new BitMatrix($dimensionX, $dimensionY); $points = fill_array(0, 2 * $dimensionX, 0.0); for ($y = 0; $y < $dimensionY; $y++) { $max = count($points); $iValue = (double) $y + 0.5; for ($x = 0; $x < $max; $x += 2) { $points[$x] = (double) ($x / 2) + 0.5; $points[$x + 1] = $iValue; } $transform->transformPoints($points); // Quick check to see if points transformed to something inside the image; // sufficient to check the endpoints $this->checkAndNudgePoints($image, $points); try { for ($x = 0; $x < $max; $x += 2) { if ($image->get((int) $points[$x], (int) $points[$x + 1])) { // Black(-ish) pixel $bits->set($x / 2, $y); } } } catch (\Exception $aioobe) { //ArrayIndexOutOfBoundsException // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting // transform gets "twisted" such that it maps a straight line of points to a set of points // whose endpoints are in bounds, but others are not. There is probably some mathematical // way to detect this about the transformation that I don't know yet. // This results in an ugly runtime exception despite our clever checks above -- can't have // that. We could check each point's coordinates but that feels duplicative. We settle for // catching and wrapping ArrayIndexOutOfBoundsException. throw NotFoundException::getNotFoundInstance(); } } return $bits; }
private static function decodeByteSegment($bits, &$result, $count, $currentCharacterSetECI, &$byteSegments, $hints) { // Don't crash trying to read more bits than we have available. if (8 * $count > $bits->available()) { throw FormatException::getFormatInstance(); } $readBytes = fill_array(0, $count, 0); for ($i = 0; $i < $count; $i++) { $readBytes[$i] = $bits->readBits(8); //(byte) } $text = implode(array_map('chr', $readBytes)); $encoding = ''; if ($currentCharacterSetECI == null) { // The spec isn't clear on this mode; see // section 6.4.5: t does not say which encoding to assuming // upon decoding. I have seen ISO-8859-1 used as well as // Shift_JIS -- without anything like an ECI designator to // give a hint. $encoding = mb_detect_encoding($text, $hints); } else { $encoding = $currentCharacterSetECI->name(); } try { // $result.= mb_convert_encoding($text ,$encoding);//(new String(readBytes, encoding)); $result .= $text; //(new String(readBytes, encoding)); } catch (UnsupportedEncodingException $ignored) { throw FormatException::getFormatInstance(); } $byteSegments = array_merge($byteSegments, $readBytes); }
/** * Calculates a single black point for each block of pixels and saves it away. * See the following thread for a discussion of this algorithm: * http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0 */ private static function calculateBlackPoints($luminances, $subWidth, $subHeight, $width, $height) { $blackPoints = fill_array(0, $subHeight, 0); foreach ($blackPoints as $key => $point) { $blackPoints[$key] = fill_array(0, $subWidth, 0); } for ($y = 0; $y < $subHeight; $y++) { $yoffset = intval32bits($y << self::$BLOCK_SIZE_POWER); $maxYOffset = $height - self::$BLOCK_SIZE; if ($yoffset > $maxYOffset) { $yoffset = $maxYOffset; } for ($x = 0; $x < $subWidth; $x++) { $xoffset = intval32bits($x << self::$BLOCK_SIZE_POWER); $maxXOffset = $width - self::$BLOCK_SIZE; if ($xoffset > $maxXOffset) { $xoffset = $maxXOffset; } $sum = 0; $min = 0xff; $max = 0; for ($yy = 0, $offset = $yoffset * $width + $xoffset; $yy < self::$BLOCK_SIZE; $yy++, $offset += $width) { for ($xx = 0; $xx < self::$BLOCK_SIZE; $xx++) { $pixel = intval32bits(intval($luminances[intval($offset + $xx)]) & 0xff); $sum += $pixel; // still looking for good contrast if ($pixel < $min) { $min = $pixel; } if ($pixel > $max) { $max = $pixel; } } // short-circuit min/max tests once dynamic range is met if ($max - $min > self::$MIN_DYNAMIC_RANGE) { // finish the rest of the rows quickly for ($yy++, $offset += $width; $yy < self::$BLOCK_SIZE; $yy++, $offset += $width) { for ($xx = 0; $xx < self::$BLOCK_SIZE; $xx++) { $sum += intval32bits($luminances[$offset + $xx] & 0xff); } } } } // The default estimate is the average of the values in the block. $average = intval32bits($sum >> self::$BLOCK_SIZE_POWER * 2); if ($max - $min <= self::$MIN_DYNAMIC_RANGE) { // If variation within the block is low, assume this is a block with only light or only // dark pixels. In that case we do not want to use the average, as it would divide this // low contrast area into black and white pixels, essentially creating data out of noise. // // The default assumption is that the block is light/background. Since no estimate for // the level of dark pixels exists locally, use half the min for the block. $average = intval($min / 2); if ($y > 0 && $x > 0) { // Correct the "white background" assumption for blocks that have neighbors by comparing // the pixels in this block to the previously calculated black points. This is based on // the fact that dark barcode symbology is always surrounded by some amount of light // background for which reasonable black point estimates were made. The bp estimated at // the boundaries is used for the interior. // The (min < bp) is arbitrary but works better than other heuristics that were tried. $averageNeighborBlackPoint = intval(($blackPoints[$y - 1][$x] + 2 * $blackPoints[$y][$x - 1] + $blackPoints[$y - 1][$x - 1]) / 4); if ($min < $averageNeighborBlackPoint) { $average = $averageNeighborBlackPoint; } } } $blackPoints[$y][$x] = intval($average); } } return $blackPoints; }
function grayScaleToBitmap($grayScale) { $middle = $this->getMiddleBrightnessPerArea($grayScale); $sqrtNumArea = count($middle); $areaWidth = floor($this->dataWidth / $sqrtNumArea); $areaHeight = floor($this->dataHeight / $sqrtNumArea); $bitmap = fill_array(0, $this->dataWidth * $this->dataHeight, 0); for ($ay = 0; $ay < $sqrtNumArea; $ay++) { for ($ax = 0; $ax < $sqrtNumArea; $ax++) { for ($dy = 0; $dy < $areaHeight; $dy++) { for ($dx = 0; $dx < $areaWidth; $dx++) { $bitmap[intval($areaWidth * $ax + $dx + ($areaHeight * $ay + $dy) * $this->dataWidth)] = $grayScale[intval($areaWidth * $ax + $dx + ($areaHeight * $ay + $dy) * $this->dataWidth)] < $middle[$ax][$ay] ? 0 : 255; } } } } return $bitmap; }
public function addResultPoints($newPoints) { $oldPoints = $this->resultPoints; if ($oldPoints == null) { $this->resultPoints = $newPoints; } else { if ($newPoints != null && count($newPoints) > 0) { $allPoints = fill_array(0, count($oldPoints) + count($newPoints), 0); $allPoints = arraycopy($oldPoints, 0, $allPoints, 0, count($oldPoints)); $allPoints = arraycopy($newPoints, 0, $allPoints, count($oldPoints), count($newPoints)); $this->resultPoints = $allPoints; } } }
/** * @return the monomial representing coefficient * x^degree */ function buildMonomial($degree, $coefficient) { if ($degree < 0) { throw new InvalidArgumentException(); } if ($coefficient == 0) { return $this->zero; } $coefficients = fill_array(0, $degree + 1, 0); //new int[degree + 1]; $coefficients[0] = $coefficient; return new GenericGFPoly($this, $coefficients); }
/** * <p>Reads the bits in the {@link BitMatrix} representing the finder pattern in the * correct order in order to reconstruct the codewords bytes contained within the * QR Code.</p> * * @return bytes encoded within the QR Code * @throws FormatException if the exact number of bytes expected is not read */ function readCodewords() { $formatInfo = $this->readFormatInformation(); $version = $this->readVersion(); // Get the data mask for the format used in this QR Code. This will exclude // some bits from reading as we wind through the bit matrix. $dataMask = DataMask::forReference($formatInfo->getDataMask()); $dimension = $this->bitMatrix->getHeight(); $dataMask->unmaskBitMatrix($this->bitMatrix, $dimension); $functionPattern = $version->buildFunctionPattern(); $readingUp = true; if ($version->getTotalCodewords()) { $result = fill_array(0, $version->getTotalCodewords(), 0); } else { $result = array(); } $resultOffset = 0; $currentByte = 0; $bitsRead = 0; // Read columns in pairs, from right to left for ($j = $dimension - 1; $j > 0; $j -= 2) { if ($j == 6) { // Skip whole column with vertical alignment pattern; // saves time and makes the other code proceed more cleanly $j--; } // Read alternatingly from bottom to top then top to bottom for ($count = 0; $count < $dimension; $count++) { $i = $readingUp ? $dimension - 1 - $count : $count; for ($col = 0; $col < 2; $col++) { // Ignore bits covered by the function pattern if (!$functionPattern->get($j - $col, $i)) { // Read a bit $bitsRead++; $currentByte <<= 1; if ($this->bitMatrix->get($j - $col, $i)) { $currentByte |= 1; } // If we've made a whole byte, save it off if ($bitsRead == 8) { $result[$resultOffset++] = $currentByte; //(byte) $bitsRead = 0; $currentByte = 0; } } } } $readingUp ^= true; // readingUp = !readingUp; // switch directions } if ($resultOffset != $version->getTotalCodewords()) { throw FormatException::getFormatInstance(); } return $result; }
private function findErrorMagnitudes($errorEvaluator, $errorLocations) { // This is directly applying Forney's Formula $s = count($errorLocations); $result = fill_array(0, $s, 0); for ($i = 0; $i < $s; $i++) { $xiInverse = $this->field->inverse($errorLocations[$i]); $denominator = 1; for ($j = 0; $j < $s; $j++) { if ($i != $j) { //denominator = field.multiply(denominator, // GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse))); // Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug. // Below is a funny-looking workaround from Steven Parkes $term = $this->field->multiply($errorLocations[$j], $xiInverse); $termPlus1 = ($term & 0x1) == 0 ? $term | 1 : $term & ~1; $denominator = $this->field->multiply($denominator, $termPlus1); } } $result[$i] = $this->field->multiply($errorEvaluator->evaluateAt($xiInverse), $this->field->inverse($denominator)); if ($this->field->getGeneratorBase() != 0) { $result[$i] = $this->field->multiply($result[$i], $xiInverse); } } return $result; }
/** * <p>Given data and error-correction codewords received, possibly corrupted by errors, attempts to * correct the errors in-place using Reed-Solomon error correction.</p> * * @param codewordBytes data and error correction codewords * @param numDataCodewords number of codewords that are data bytes * @throws ChecksumException if error correction fails */ private function correctErrors(&$codewordBytes, $numDataCodewords) { $numCodewords = count($codewordBytes); // First read into an array of ints $codewordsInts = fill_array(0, $numCodewords, 0); for ($i = 0; $i < $numCodewords; $i++) { $codewordsInts[$i] = $codewordBytes[$i] & 0xff; } $numECCodewords = count($codewordBytes) - $numDataCodewords; try { $this->rsDecoder->decode($codewordsInts, $numECCodewords); } catch (ReedSolomonException $ignored) { throw ChecksumException::getChecksumInstance(); } // Copy back into array of bytes -- only need to worry about the bytes that were data // We don't care about errors in the error-correction codewords for ($i = 0; $i < $numDataCodewords; $i++) { $codewordBytes[$i] = $codewordsInts[$i]; } }