static calculateBlackPoints(luminances, subWidth /*int*/, subHeight /*int*/, width /*int*/, height /*int*/) {
        const maxYOffset = height - HybridBinarizer.BLOCK_SIZE;
        const maxXOffset = width - HybridBinarizer.BLOCK_SIZE;
        // tslint:disable-next-line:whitespace
        const blackPoints = new Array(subHeight); // subWidth
        for (let y = 0; y < subHeight; y++) {
            blackPoints[y] = new Int32Array(subWidth);
            let yoffset = y << HybridBinarizer.BLOCK_SIZE_POWER;
            if (yoffset > maxYOffset) {
                yoffset = maxYOffset;
            }
            for (let x = 0; x < subWidth; x++) {
                let xoffset = x << HybridBinarizer.BLOCK_SIZE_POWER;
                if (xoffset > maxXOffset) {
                    xoffset = maxXOffset;
                }
                let sum = 0;
                let min = 0xFF;
                let max = 0;
                for (let yy = 0, offset = yoffset * width + xoffset; yy < HybridBinarizer.BLOCK_SIZE; yy++, offset += width) {
                    for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) {
                        const pixel = luminances[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 > HybridBinarizer.MIN_DYNAMIC_RANGE) {
                        // finish the rest of the rows quickly
                        for (yy++, offset += width; yy < HybridBinarizer.BLOCK_SIZE; yy++, offset += width) {
                            for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) {
                                sum += luminances[offset + xx] & 0xFF;
                            }
                        }
                    }
                }
                // The default estimate is the average of the values in the block.
                let average = sum >> (HybridBinarizer.BLOCK_SIZE_POWER * 2);
                if (max - min <= HybridBinarizer.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 = 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.
                        const averageNeighborBlackPoint = (blackPoints[y - 1][x] + (2 * blackPoints[y][x - 1]) + blackPoints[y - 1][x - 1]) / 4;
                        if (min < averageNeighborBlackPoint) {
                            average = averageNeighborBlackPoint;
                        }
                    }
                }
                blackPoints[y][x] = average;
            }
        }
        return blackPoints;
    }
/**
     * 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
     */
Calculates a single black point for each block of pixels and saves it away.
Calculates a single black point for each block of pixels and saves it away .
static calculateBlackPoints(luminances, subWidth , subHeight , width , height ) {
        const maxYOffset = height - HybridBinarizer.BLOCK_SIZE;
        const maxXOffset = width - HybridBinarizer.BLOCK_SIZE;
        const blackPoints = new Array(subHeight); 
        for (let y = 0; y < subHeight; y++) {
            blackPoints[y] = new Int32Array(subWidth);
            let yoffset = y << HybridBinarizer.BLOCK_SIZE_POWER;
            if (yoffset > maxYOffset) {
                yoffset = maxYOffset;
            }
            for (let x = 0; x < subWidth; x++) {
                let xoffset = x << HybridBinarizer.BLOCK_SIZE_POWER;
                if (xoffset > maxXOffset) {
                    xoffset = maxXOffset;
                }
                let sum = 0;
                let min = 0xFF;
                let max = 0;
                for (let yy = 0, offset = yoffset * width + xoffset; yy < HybridBinarizer.BLOCK_SIZE; yy++, offset += width) {
                    for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) {
                        const pixel = luminances[offset + xx] & 0xFF;
                        sum += pixel;
                        if (pixel < min) {
                            min = pixel;
                        }
                        if (pixel > max) {
                            max = pixel;
                        }
                    }
                    if (max - min > HybridBinarizer.MIN_DYNAMIC_RANGE) {
                        for (yy++, offset += width; yy < HybridBinarizer.BLOCK_SIZE; yy++, offset += width) {
                            for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) {
                                sum += luminances[offset + xx] & 0xFF;
                            }
                        }
                    }
                }
                let average = sum >> (HybridBinarizer.BLOCK_SIZE_POWER * 2);
                if (max - min <= HybridBinarizer.MIN_DYNAMIC_RANGE) {
                     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 = 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.
                        const averageNeighborBlackPoint = (blackPoints[y - 1][x] + (2 * blackPoints[y][x - 1]) + blackPoints[y - 1][x - 1]) / 4;
                        if (min < averageNeighborBlackPoint) {
                            average = averageNeighborBlackPoint;
                        }
                    }
                }
                blackPoints[y][x] = average;
            }
        }
        return blackPoints;
    }
static calculateBlackPoints ( luminances , subWidth , subHeight , width , height ) { const maxYOffset = height - HybridBinarizer . BLOCK_SIZE ; const maxXOffset = width - HybridBinarizer . BLOCK_SIZE ; const blackPoints = new Array ( subHeight ) ; for ( let y = 0 ; y < subHeight ; y ++ ) { blackPoints [ y ] = new Int32Array ( subWidth ) ; let yoffset = y << HybridBinarizer . BLOCK_SIZE_POWER ; if ( yoffset > maxYOffset ) { yoffset = maxYOffset ; } for ( let x = 0 ; x < subWidth ; x ++ ) { let xoffset = x << HybridBinarizer . BLOCK_SIZE_POWER ; if ( xoffset > maxXOffset ) { xoffset = maxXOffset ; } let sum = 0 ; let min = 0xFF ; let max = 0 ; for ( let yy = 0 , offset = yoffset * width + xoffset ; yy < HybridBinarizer . BLOCK_SIZE ; yy ++ , offset += width ) { for ( let xx = 0 ; xx < HybridBinarizer . BLOCK_SIZE ; xx ++ ) { const pixel = luminances [ offset + xx ] & 0xFF ; sum += pixel ; if ( pixel < min ) { min = pixel ; } if ( pixel > max ) { max = pixel ; } } if ( max - min > HybridBinarizer . MIN_DYNAMIC_RANGE ) { for ( yy ++ , offset += width ; yy < HybridBinarizer . BLOCK_SIZE ; yy ++ , offset += width ) { for ( let xx = 0 ; xx < HybridBinarizer . BLOCK_SIZE ; xx ++ ) { sum += luminances [ offset + xx ] & 0xFF ; } } } } let average = sum >> ( HybridBinarizer . BLOCK_SIZE_POWER * 2 ) ; if ( max - min <= HybridBinarizer . MIN_DYNAMIC_RANGE ) { average = min / 2 ; if ( y > 0 && x > 0 ) { const averageNeighborBlackPoint = ( blackPoints [ y - 1 ] [ x ] + ( 2 * blackPoints [ y ] [ x - 1 ] ) + blackPoints [ y - 1 ] [ x - 1 ] ) / 4 ; if ( min < averageNeighborBlackPoint ) { average = averageNeighborBlackPoint ; } } } blackPoints [ y ] [ x ] = average ; } } return blackPoints ; }
Calculates a single black point for each block of pixels and saves it away.
Calculates a single black point for each block of pixels and saves it away .
/*int*/ /*int*/ /*int*/ /*int*/ // tslint:disable-next-line:whitespace // subWidth // still looking for good contrast // short-circuit min/max tests once dynamic range is met // finish the rest of the rows quickly // The default estimate is the average of the values in the block. // 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. // 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.