docs: public void process(GrayU8 binary , GrayS32 labeled ) {
  		// initialize data structures
  		labeled.reshape(binary.width,binary.height);
  
  		// ensure that the image border pixels are filled with zero by enlarging the image
  		if( border.width != binary.width+2 || border.height != binary.height+2)  {
  			border.reshape(binary.width + 2, binary.height + 2);
  			ImageMiscOps.fillBorder(border, 0, 1);
  		}
  		border.subimage(1,1,border.width-1,border.height-1, null).setTo(binary);
  
  		// labeled image must initially be filled with zeros
  		ImageMiscOps.fill(labeled,0);
  
  		binary = border;
  		packedPoints.reset();
  		contours.reset();
  		tracer.setInputs(binary,labeled, packedPoints);
  
  		// Outside border is all zeros so it can be ignored
  		int endY = binary.height-1, enxX = binary.width-1;
  		for( y = 1; y < endY; y++ ) {
  			indexIn = binary.startIndex + y*binary.stride+1;
  			indexOut = labeled.startIndex + (y-1)*labeled.stride;
  
  			x = 1;
  			int delta = scanForOne(binary.data,indexIn,indexIn+enxX-x)-indexIn;
  			x += delta;
  			indexIn += delta;
  			indexOut += delta;
  			while( x < enxX ) {
  				int label = labeled.data[indexOut];
  				boolean handled = false;
  				if( label == 0 && binary.data[indexIn - binary.stride ] != 1 ) {
  					handleStep1();
  					handled = true;
  					label = contours.size;
  				}
  				// could be an external and internal contour
  				if( binary.data[indexIn + binary.stride ] == 0 ) {
  					handleStep2(labeled, label);
  					handled = true;
  				}
  				if( !handled ) {
  					// Step 3: Must not be part of the contour but an inner pixel and the pixel to the left must be
  					// labeled
  					if( labeled.data[indexOut] == 0 )
  						labeled.data[indexOut] = labeled.data[indexOut-1];
  				}
  
  				delta = scanForOne(binary.data,indexIn+1,indexIn+enxX-x)-indexIn;
  				x += delta;
  				indexIn += delta;
  				indexOut += delta;
  			}
  		}
  	}