Serializing Tracking Data

The LeapFrame 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 LeapFrame instance, use LeapFrame.serialize.

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

NSData *serializedFrame = [frameToSave serialize];
BOOL success = [serializedFrame writeToFile:@"frame.data" atomically:YES];

Deserializing a Frame

Before you can deserialize LeapFrame data, you must create a Controller object. If you want to access any LeapGesture data in the restored frame, you must enable the gesture using the LeapController.enableGesture:enable: 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 LeapController instance if one doesn’t already exist.
  2. Acquire the data and, if necessary, convert it into the proper data type.
  3. Create a LeapFrame 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 LeapFrame 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 LeapFrame object.

NSData *serializedData = [NSData dataWithContentsOfFile:@"frame.data"];
LeapFrame *newFrame = [LeapFrame deserialize:serializedData];

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.

[[NSFileManager defaultManager] createFileAtPath:@"frames.data"
                                contents:nil
                                attributes:nil];
NSFileHandle *outFile = [NSFileHandle fileHandleForWritingAtPath:@"frames.data"];
if(outFile) {
    for (int f = 0; f <= 9; f++) {
        LeapFrame *toSerialize = [controller frame:(9 - f)];
        NSData *serializedFrame = [toSerialize serialize];
        int32_t dataLength = (int32_t)serializedFrame.length;
        NSData *dataSize = [NSData dataWithBytes:&dataLength length:sizeof(dataLength)];
        [outFile writeData:dataSize];
        [outFile writeData:serializedFrame];
    }
}

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.

NSFileHandle *inFile = [NSFileHandle fileHandleForReadingAtPath:@"frames.data"];
if(inFile) {
    [inFile seekToEndOfFile];
    NSUInteger fileLength = inFile.offsetInFile;
    [inFile seekToFileOffset:0];
    int32_t frameSize;
    NSData *storedLength = [inFile readDataOfLength:sizeof(int32_t)];
    [storedLength getBytes:&frameSize length:sizeof(int32_t)];
    while (inFile.offsetInFile + frameSize <= fileLength) {
        NSData *frameData = [inFile readDataOfLength:frameSize];
        NSData *storedLength = [inFile readDataOfLength:sizeof(int32_t)];
        [storedLength getBytes:&frameSize length:sizeof(int32_t)];
        LeapFrame *deserializedFrame = [LeapFrame deserialize:frameData];
    }
}