import BinaryBitmap from '../BinaryBitmap' ; import BitArray from '../common/BitArray' ; import DecodeHintType from '../DecodeHintType' ; import Reader from '../Reader' ; import Result from '../Result' ; import ResultMetadataType from '../ResultMetadataType' ; import ResultPoint from '../ResultPoint' ; import NotFoundException from '../NotFoundException' ; author dswitkin google author Sean Owen
  export default abstract class OneDReader implements Reader { public decode ( image , hints ? ) { try { return this . doDecode ( image , hints ) ; } catch ( nfe ) { const tryHarder = hints && ( hints . get ( DecodeHintType . TRY_HARDER ) === true ) ; if ( tryHarder && image . isRotateSupported ( ) ) { const rotatedImage = image . rotateCounterClockwise ( ) ; const result = this . doDecode ( rotatedImage , hints ) ; const metadata = result . getResultMetadata ( ) ; let orientation = 270 ; if ( metadata !== null && ( metadata . get ( ResultMetadataType . ORIENTATION ) === true ) ) { orientation = ( orientation + ( metadata . get ( ResultMetadataType . ORIENTATION ) as number ) % 360 ) ; } result . putMetadata ( ResultMetadataType . ORIENTATION , orientation ) ; const points = result . getResultPoints ( ) ; if ( points !== null ) { const height = rotatedImage . getHeight ( ) ; for ( let i = 0 ; i < points . length ; i ++ ) { points [ i ] = new ResultPoint ( height - points [ i ] . getY ( ) - 1 , points [ i ] . getX ( ) ) ; } } return result ; } else { throw new NotFoundException ( ) ; } } } public reset ( ) { } param image param hints return throws private doDecode ( image , hints ? ) { const width = image . getWidth ( ) ; const height = image . getHeight ( ) ; let row = new BitArray ( width ) ; const tryHarder = hints && ( hints . get ( DecodeHintType . TRY_HARDER ) === true ) ; const rowStep = Math . max ( 1 , height >> ( tryHarder ? 8 : 5 ) ) ; let maxLines ; if ( tryHarder ) { maxLines = height ; } else { maxLines = 15 ; } const middle = Math . trunc ( height / 2 ) ; for ( let x = 0 ; x < maxLines ; x ++ ) { const rowStepsAboveOrBelow = Math . trunc ( ( x + 1 ) / 2 ) ; const isAbove = ( x & 0x01 ) === 0 ; const rowNumber = middle + rowStep * ( isAbove ? rowStepsAboveOrBelow : - rowStepsAboveOrBelow ) ; if ( rowNumber < 0 || rowNumber >= height ) { break ; } try { row = image . getBlackRow ( rowNumber , row ) ; } catch ( ignored ) { continue ; } for ( let attempt = 0 ; attempt < 2 ; attempt ++ ) { if ( attempt === 1 ) { row . reverse ( ) ; if ( hints && ( hints . get ( DecodeHintType . NEED_RESULT_POINT_CALLBACK ) === true ) ) { const newHints = new Map ( ) ; hints . forEach ( ( hint , key ) => newHints . set ( key , hint ) ) ; newHints . delete ( DecodeHintType . NEED_RESULT_POINT_CALLBACK ) ; hints = newHints ; } } try { const result = this . decodeRow ( rowNumber , row , hints ) ; if ( attempt === 1 ) { result . putMetadata ( ResultMetadataType . ORIENTATION , 180 ) ; const points = result . getResultPoints ( ) ; if ( points !== null ) { points [ 0 ] = new ResultPoint ( width - points [ 0 ] . getX ( ) - 1 , points [ 0 ] . getY ( ) ) ; points [ 1 ] = new ResultPoint ( width - points [ 1 ] . getX ( ) - 1 , points [ 1 ] . getY ( ) ) ; } } return result ; } catch ( re ) { } } } throw new NotFoundException ( ) ; } param row param start param counters throws protected static recordPattern ( row , start , counters ) { const numCounters = counters . length ; for ( let index = 0 ; index < numCounters ; index ++ ) counters [ index ] = 0 ; const end = row . getSize ( ) ; if ( start >= end ) { throw new NotFoundException ( ) ; } let isWhite = ! row . get ( start ) ; let counterPosition = 0 ; let i = start ; while ( i < end ) { if ( row . get ( i ) !== isWhite ) { counters [ counterPosition ] ++ ; } else { if ( ++ counterPosition === numCounters ) { break ; } else { counters [ counterPosition ] = 1 ; isWhite = ! isWhite ; } } i ++ ; } if ( ! ( counterPosition === numCounters || ( counterPosition === numCounters - 1 && i === end ) ) ) { throw new NotFoundException ( ) ; } } protected static recordPatternInReverse ( row , start , counters ) { let numTransitionsLeft = counters . length ; let last = row . get ( start ) ; while ( start > 0 && numTransitionsLeft >= 0 ) { if ( row . get ( -- start ) !== last ) { numTransitionsLeft -- ; last = ! last ; } } if ( numTransitionsLeft >= 0 ) { throw new NotFoundException ( ) ; } OneDReader . recordPattern ( row , start + 1 , counters ) ; } param counters param pattern param maxIndividualVariance return protected static patternMatchVariance ( counters , pattern , maxIndividualVariance ) { const numCounters = counters . length ; let total = 0 ; let patternLength = 0 ; for ( let i = 0 ; i < numCounters ; i ++ ) { total += counters [ i ] ; patternLength += pattern [ i ] ; } if ( total < patternLength ) { return Number . POSITIVE_INFINITY ; } const unitBarWidth = total / patternLength ; maxIndividualVariance *= unitBarWidth ; let totalVariance = 0.0 ; for ( let x = 0 ; x < numCounters ; x ++ ) { const counter = counters [ x ] ; const scaledPattern = pattern [ x ] * unitBarWidth ; const variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter ; if ( variance > maxIndividualVariance ) { return Number . POSITIVE_INFINITY ; } totalVariance += variance ; } return totalVariance / total ; } param rowNumber param row param hints return { link throws throws throws public abstract decodeRow ( rowNumber , row , hints ? ) ; }