Serializing Tracking Data

The Frame class provides methods for serializing the data in a frame as a sequence of bytes. You can pass this sequence of bytes to the deserializer to create a new copy of the original frame.

Serializing a Frame

To serialize a Frame instance, use Frame.serialize().

The following example serializes a frame and saves it to a file.

std::ofstream outputFile("frame.data");
const std::string serializedFrame = frame.serialize();
outputFile << serializedFrame;
outputFile.close();

Deserializing a Frame

Before you can deserialize Frame data, you must create a Controller object. If you want to access any Gesture data in the restored frame, you must enable the gesture using the Controller.enableGesture() function. Accessing images stored in the frame data is not supported at this time. Deserializing data serialized by a different version of the Leap Motion SDK is not officially supported; it may work if there are no data model differences between the two versions.

To deserialize frame data:

  1. Create a Controller instance if one doesn’t already exist.
  2. Acquire the data and, if necessary, convert it into the proper data type.
  3. Create a Frame object.
  4. Call the new frame’s deserialize() function.

Note that the reconstructed data replaces the existing data in the frame. If you use an existing, valid Frame instance, its existing data is replaced; however, any child objects, like hands or fingers, remain valid as long as you maintain a separate reference to them.

The following example loads data from a file and deserializes it to create a Frame object.

Leap::Controller controller; //An instance must exist
std::ifstream inputFile("frame.data");
std::string frameData((std::istreambuf_iterator<char>(inputFile)), std::istreambuf_iterator<char>());
Leap::Frame reconstructedFrame;
reconstructedFrame.deserialize(frameData);

Saving and Loading Multiple Frames

If you wish to save several frames to the same file, you will have to devise a way to tell where one frame ends and the next begins. The size of the data can vary from frame-to-frame. The following example illustrates one way to do this, which is to store a 4 byte integer containing the size of the data immediately before the data itself.

std::string outFilename = "frames.data";
std::fstream out(outFilename, std::ios_base::trunc | std::ios_base::out);
if(out)
{
    for (int f = 9; f >= 0; f--) {
        Leap::Frame frameToSerialize = controller.frame(f);
        std::string serialized = frameToSerialize.serialize();
        out << (long)serialized.length() << serialized;
    }
    out.flush();
    out.close();
}
else if(errno) {
    std::cout << "Error: " << errno << std::endl;
    std::cout << "Couldn't open " << outFilename << " for writing." << std::endl;
}

To read the frame data from the saved file, you can then read the first 4 bytes of the file to determine how much data to read to get an entire frame. Simply repeat the process until you reach the end of the file.

std::vector<Leap::Frame> deserializedFrames;
std::string inFilename = "frames.data";
std::ifstream in(inFilename, std::fstream::in);
std::string contents;
if (in)
{
    in.seekg(0, std::ios::beg);
    long nextBlockSize = 0;
    in >> nextBlockSize;
    while (!in.eof())
    {
        contents.resize(nextBlockSize);
        in.read(&contents[0], nextBlockSize);
        Leap::Frame newFrame;
        newFrame.deserialize(contents);
        if(newFrame.isValid()) deserializedFrames.push_back(newFrame);
        in >> nextBlockSize;
    }
    in.close();
}
else if(errno){
    std::cout << "Error: " << errno << std::endl;
    std::cout << "Couldn't open " << inFilename << " for reading." << std::endl;
}