import BarcodeFormat from '../BarcodeFormat' ; import BitArray from '../common/BitArray' ; import DecodeHintType from '../DecodeHintType' ; import FormatException from '../FormatException' ; import NotFoundException from '../NotFoundException' ; import Result from '../Result' ; import ResultPoint from '../ResultPoint' ; import StringBuilder from '../util/StringBuilder' ; import System from '../util/System' ; import OneDReader from './OneDReader' ; author Tjieco
  export default class ITFReader extends OneDReader { private static PATTERNS : Int32Array [ ] = [ Int32Array . from ( [ 1 , 1 , 2 , 2 , 1 ] ) , Int32Array . from ( [ 2 , 1 , 1 , 1 , 2 ] ) , Int32Array . from ( [ 1 , 2 , 1 , 1 , 2 ] ) , Int32Array . from ( [ 2 , 2 , 1 , 1 , 1 ] ) , Int32Array . from ( [ 1 , 1 , 2 , 1 , 2 ] ) , Int32Array . from ( [ 2 , 1 , 2 , 1 , 1 ] ) , Int32Array . from ( [ 1 , 2 , 2 , 1 , 1 ] ) , Int32Array . from ( [ 1 , 1 , 1 , 2 , 2 ] ) , Int32Array . from ( [ 2 , 1 , 1 , 2 , 1 ] ) , Int32Array . from ( [ 1 , 2 , 1 , 2 , 1 ] ) , Int32Array . from ( [ 1 , 1 , 3 , 3 , 1 ] ) , Int32Array . from ( [ 3 , 1 , 1 , 1 , 3 ] ) , Int32Array . from ( [ 1 , 3 , 1 , 1 , 3 ] ) , Int32Array . from ( [ 3 , 3 , 1 , 1 , 1 ] ) , Int32Array . from ( [ 1 , 1 , 3 , 1 , 3 ] ) , Int32Array . from ( [ 3 , 1 , 3 , 1 , 1 ] ) , Int32Array . from ( [ 1 , 3 , 3 , 1 , 1 ] ) , Int32Array . from ( [ 1 , 1 , 1 , 3 , 3 ] ) , Int32Array . from ( [ 3 , 1 , 1 , 3 , 1 ] ) , Int32Array . from ( [ 1 , 3 , 1 , 3 , 1 ] ) ] ; private static MAX_AVG_VARIANCE = 0.38 ; private static MAX_INDIVIDUAL_VARIANCE = 0.5 ; private static DEFAULT_ALLOWED_LENGTHS : number [ ] = [ 6 , 8 , 10 , 12 , 14 ] ; private narrowLineWidth = - 1 ; private static START_PATTERN = Int32Array . from ( [ 1 , 1 , 1 , 1 ] ) ; private static END_PATTERN_REVERSED : Int32Array [ ] = [ Int32Array . from ( [ 1 , 1 , 2 ] ) , Int32Array . from ( [ 1 , 1 , 3 ] ) ] ; public decodeRow ( rowNumber , row , hints ? ) { let startRange = this . decodeStart ( row ) ; let endRange = this . decodeEnd ( row ) ; let result = new StringBuilder ( ) ; ITFReader . decodeMiddle ( row , startRange [ 1 ] , endRange [ 0 ] , result ) ; let resultString = result . toString ( ) ; let allowedLengths = null ; if ( hints != null ) { allowedLengths = hints . get ( DecodeHintType . ALLOWED_LENGTHS ) ; } if ( allowedLengths == null ) { allowedLengths = ITFReader . DEFAULT_ALLOWED_LENGTHS ; } let length = resultString . length ; let lengthOK = false ; let maxAllowedLength = 0 ; for ( let value of allowedLengths ) { if ( length === value ) { lengthOK = true ; break ; } if ( value > maxAllowedLength ) { maxAllowedLength = value ; } } if ( ! lengthOK && length > maxAllowedLength ) { lengthOK = true ; } if ( ! lengthOK ) { throw new FormatException ( ) ; } const points = [ new ResultPoint ( startRange [ 1 ] , rowNumber ) , new ResultPoint ( endRange [ 0 ] , rowNumber ) ] ; let resultReturn = new Result ( resultString , null , 0 , points , BarcodeFormat . ITF , new Date ( ) . getTime ( ) ) ; return resultReturn ; } private static decodeMiddle ( row , payloadStart , payloadEnd , resultString ) { let counterDigitPair = new Int32Array ( 10 ) ; let counterBlack = new Int32Array ( 5 ) ; let counterWhite = new Int32Array ( 5 ) ; counterDigitPair . fill ( 0 ) ; counterBlack . fill ( 0 ) ; counterWhite . fill ( 0 ) ; while ( payloadStart < payloadEnd ) { OneDReader . recordPattern ( row , payloadStart , counterDigitPair ) ; for ( let k = 0 ; k < 5 ; k ++ ) { let twoK = 2 * k ; counterBlack [ k ] = counterDigitPair [ twoK ] ; counterWhite [ k ] = counterDigitPair [ twoK + 1 ] ; } let bestMatch = ITFReader . decodeDigit ( counterBlack ) ; resultString . append ( bestMatch . toString ( ) ) ; bestMatch = this . decodeDigit ( counterWhite ) ; resultString . append ( bestMatch . toString ( ) ) ; counterDigitPair . forEach ( function ( counterDigit ) { payloadStart += counterDigit ; } ) ; } } private decodeStart ( row ) { let endStart = ITFReader . skipWhiteSpace ( row ) ; let startPattern = ITFReader . findGuardPattern ( row , endStart , ITFReader . START_PATTERN ) ; this . narrowLineWidth = ( startPattern [ 1 ] - startPattern [ 0 ] ) / 4 ; this . validateQuietZone ( row , startPattern [ 0 ] ) ; return startPattern ; } private validateQuietZone ( row , startPattern ) { let quietCount = this . narrowLineWidth * 10 ; quietCount = quietCount < startPattern ? quietCount : startPattern ; for ( let i = startPattern - 1 ; quietCount > 0 && i >= 0 ; i -- ) { if ( row . get ( i ) ) { break ; } quietCount -- ; } if ( quietCount !== 0 ) { throw new NotFoundException ( ) ; } } private static skipWhiteSpace ( row ) { const width = row . getSize ( ) ; const endStart = row . getNextSet ( 0 ) ; if ( endStart === width ) { throw new NotFoundException ( ) ; } return endStart ; } private decodeEnd ( row ) { row . reverse ( ) ; try { let endStart = ITFReader . skipWhiteSpace ( row ) ; let endPattern ; try { endPattern = ITFReader . findGuardPattern ( row , endStart , ITFReader . END_PATTERN_REVERSED [ 0 ] ) ; } catch ( error ) { if ( error instanceof NotFoundException ) { endPattern = ITFReader . findGuardPattern ( row , endStart , ITFReader . END_PATTERN_REVERSED [ 1 ] ) ; } } this . validateQuietZone ( row , endPattern [ 0 ] ) ; let temp = endPattern [ 0 ] ; endPattern [ 0 ] = row . getSize ( ) - endPattern [ 1 ] ; endPattern [ 1 ] = row . getSize ( ) - temp ; return endPattern ; } finally { row . reverse ( ) ; } } private static findGuardPattern ( row , rowOffset , pattern ) { let patternLength = pattern . length ; let counters = new Int32Array ( patternLength ) ; let width = row . getSize ( ) ; let isWhite = false ; let counterPosition = 0 ; let patternStart = rowOffset ; counters . fill ( 0 ) ; for ( let x = rowOffset ; x < width ; x ++ ) { if ( row . get ( x ) !== isWhite ) { counters [ counterPosition ] ++ ; } else { if ( counterPosition === patternLength - 1 ) { if ( OneDReader . patternMatchVariance ( counters , pattern , ITFReader . MAX_INDIVIDUAL_VARIANCE ) < ITFReader . MAX_AVG_VARIANCE ) { return [ patternStart , x ] ; } patternStart += counters [ 0 ] + counters [ 1 ] ; System . arraycopy ( counters , 2 , counters , 0 , counterPosition - 1 ) ; counters [ counterPosition - 1 ] = 0 ; counters [ counterPosition ] = 0 ; counterPosition -- ; } else { counterPosition ++ ; } counters [ counterPosition ] = 1 ; isWhite = ! isWhite ; } } throw new NotFoundException ( ) ; } private static decodeDigit ( counters ) { let bestVariance = ITFReader . MAX_AVG_VARIANCE ; let bestMatch = - 1 ; let max = ITFReader . PATTERNS . length ; for ( let i = 0 ; i < max ; i ++ ) { let pattern = ITFReader . PATTERNS [ i ] ; let variance = OneDReader . patternMatchVariance ( counters , pattern , ITFReader . MAX_INDIVIDUAL_VARIANCE ) ; if ( variance < bestVariance ) { bestVariance = variance ; bestMatch = i ; } else if ( variance === bestVariance ) { bestMatch = - 1 ; } } if ( bestMatch >= 0 ) { return bestMatch % 10 ; } else { throw new NotFoundException ( ) ; } } }