docs: public static BufferedImage colorizeGradient(GrayS16 derivX, GrayS16 derivY, int maxAbsValue, BufferedImage output) {
  		InputSanityCheck.checkSameShape(derivX,derivY);
  
  		if( output == null )
  			output = new BufferedImage(derivX.width,derivX.height,BufferedImage.TYPE_INT_RGB);
  
  		WritableRaster raster = output.getRaster();
  		DataBufferInt buffer = (DataBufferInt)raster.getDataBuffer();
  		int[] outData = buffer.getData();
  		int outOffset = ConvertRaster.getOffset(raster);
  
  		if( maxAbsValue < 0 ) {
  			maxAbsValue = ImageStatistics.maxAbs(derivX);
  			maxAbsValue = Math.max(maxAbsValue, ImageStatistics.maxAbs(derivY));
  		}
  		if( maxAbsValue == 0 )
  			return output;
  
  		int indexOut = outOffset;
  
  		for( int y = 0; y < derivX.height; y++ ) {
  			int indexX = derivX.startIndex + y*derivX.stride;
  			int indexY = derivY.startIndex + y*derivY.stride;
  
  			for( int x = 0; x < derivX.width; x++ ) {
  				int valueX = derivX.data[ indexX++ ];
  				int valueY = derivY.data[ indexY++ ];
  
  				int r=0,g=0,b=0;
  
  				if( valueX > 0 ) {
  					r = 255*valueX/maxAbsValue;
  				} else {
  					g = -255*valueX/maxAbsValue;
  				}
  				if( valueY > 0 ) {
  					b = 255*valueY/maxAbsValue;
  				} else {
  					int v = -255*valueY/maxAbsValue;
  					r += v;
  					g += v;
  					if( r > 255 ) r = 255;
  					if( g > 255 ) g = 255;
  				}
  
  				outData[indexOut++] = r << 16 | g << 8 | b;
  			}
  		}
  
  		return output;
  	}