E57 Simple API V1.0.312  Aug. 10, 2012
E57 Simple API V1.0.312 Documentation

Introduction

This browser-based document describes the E57 Simple API (Application Programmer Interface) version 0.52, which is a collection of functions that help a C++ programmer wrap the E57 Foundation API.

Reading using the E57 Simple API

An example of a typical use of this interface would be as follows:

        try
        {
Create a ReaderImpl

                _bstr_t bsFile = sFile;                 //converts Unicode to UTF-8
                e57::Reader     eReader( (char*) bsFile);

/////////////////////////////////////////////////////////////
ACCESSING ROOT DATA

Read the root

                e57::E57Root    rootHeader;
                eReader.GetE57Root( rootHeader);

Access all the root information like

                char* fileGuid = rootHeader.guid.c_str();
                double fileGPSTime = rootHeader.creationDateTime;
                ...

/////////////////////////////////////////////////////////////
ACCESSING SCAN DATA3D

Get the number of scan images available

                int data3DCount = eReader.GetData3DCount();

selecting the first scan

                int scanIndex = 0;

Read the scan 0 header.

                e57::Data3D             scanHeader;
                eReader.ReadData3D( scanIndex, scanHeader);

Access all the header information

                _bstr_t bstrName = scanHeader.name.c_str();
                _bstr_t bstrGuid = scanHeader.guid.c_str();
                _bstr_t bstrDesc = scanHeader.description.c_str();

                double startGPSTime = rootHeader.acquisitionStart;
                double endGPSTime = rootHeader.acquisitionEnd;

Get pose information

                ISI::Point translation;
                translation.x(scanHeader.pose.translation.x);
                translation.y(scanHeader.pose.translation.y);
                translation.z(scanHeader.pose.translation.z);

                ISI::Quat rotation;
                rotation.w(scanHeader.pose.rotation.w);
                rotation.x(scanHeader.pose.rotation.x);
                rotation.y(scanHeader.pose.rotation.y);
                rotation.z(scanHeader.pose.rotation.z);

Get scanner information

                _bstr_t bstrSerial = scanHeader.sensorSerialNumber.c_str();
                _bstr_t bstrVendor = scanHeader.sensorVendor.c_str();
                _bstr_t bstrModel = scanHeader.sensorModel.c_str();
                _bstr_t bstrSoftware = scanHeader.sensorSoftwareVersion.c_str();
                _bstr_t bstrFirmware = scanHeader.sensorFirmwareVersion.c_str();
                _bstr_t bstrHardware = scanHeader.sensorHardwareVersion.c_str();

Get environment information

                double temperature = scanHeader.temperature;
                double humidity = scanHeader.relativeHumidity;
                double airPressure = scanHeader.atmosphericPressure;

                ...

///////////////////////////////////////////////////////////////
ACCESSING SCAN DATA

Get the Size of the Scan
                int64_t nColumn = 0;    
                int64_t nRow = 0;

                int64_t nPointsSize = 0;        //Number of points

                int64_t nGroupsSize = 0;        //Number of groups
                int64_t nCountSize = 0;         //Number of points per group
                bool    bColumnIndex = false; //indicates that idElementName is "columnIndex"

                eReader.GetData3DSizes( scanIndex, nRow, nColumn, nPointsSize, nGroupsSize, nCountSize, bColumnIndex);

                int64_t nSize = nRow;
                if(nSize == 0) nSize = 1024;    // choose a chunk size

Setup buffers

                int8_t * isInvalidData = NULL;
                if(scanHeader.pointFields.cartesianInvalidStateField)
                        isInvalidData = new int8_t[nSize];

Setup Points Buffers

                double * xData = NULL;
                if(scanHeader.pointFields.cartesianXField)
                        xData = new double[nSize];

                double * yData = NULL;
                if(scanHeader.pointFields.cartesianYField)
                        yData = new double[nSize];

                double * zData = NULL;
                if(scanHeader.pointFields.cartesianZField)
                        zData = new double[nSize];

Setup intensity buffers if present

                double *        intData = NULL;
                bool            bIntensity = false;
                double          intRange = 0;
                double          intOffset = 0;

                if(scanHeader.pointFields.intensityField)
                {
                        bIntensity = true;
                        intData = new double[nSize];
                        intRange = scanHeader.intensityLimits.intensityMaximum - scanHeader.intensityLimits.intensityMinimum;
                        intOffset = scanHeader.intensityLimits.intensityMinimum;
                }

Setup color buffers if present

                uint16_t *      redData = NULL;
                uint16_t *      greenData = NULL;
                uint16_t *      blueData = NULL;
                bool            bColor = false;
                int32_t         colorRedRange = 1;
                int32_t         colorRedOffset = 0;
                int32_t         colorGreenRange = 1;
                int32_t         colorGreenOffset = 0;
                int32_t         colorBlueRange = 1;
                int32_t         colorBlueOffset = 0;

                if(header.pointFields.colorRedField)
                {
                        bColor = true;
                        redData = new uint16_t[nSize];
                        greenData = new uint16_t[nSize];
                        blueData = new uint16_t[nSize];
                        colorRedRange = header.colorLimits.colorRedMaximum - header.colorLimits.colorRedMinimum;
                        colorRedOffset = header.colorLimits.colorRedMinimum;
                        colorGreenRange = header.colorLimits.colorGreenMaximum - header.colorLimits.colorGreenMinimum;
                        colorGreenOffset = header.colorLimits.colorGreenMinimum;
                        colorBlueRange = header.colorLimits.colorBlueMaximum - header.colorLimits.colorBlueMinimum;
                        colorBlueOffset = header.colorLimits.colorBlueMinimum;
                }

Setup the GroupByLine buffers information

                int64_t * idElementValue = NULL;
                int64_t * startPointIndex = NULL;
                int64_t * pointCount = NULL;
                if(nGroupsSize > 0)
                {
                        idElementValue = new int64_t[nGroupsSize];
                        startPointIndex = new int64_t[nGroupsSize];
                        pointCount = new int64_t[nGroupsSize];

                        if(!eReader.ReadData3DGroupsData(scanIndex, nGroupsSize, idElementValue,
                                startPointIndex, pointCount))
                                nGroupsSize = 0;
                }

Setup row/column index information

                int32_t * rowIndex = NULL;
                int32_t * columnIndex = NULL;
                if(scanHeader.pointFields.rowIndexField)
                        rowIndex = new int32_t[nSize];
                if(scanHeader.pointFields.columnIndexField)
                        columnIndex = new int32_t[nRow];

Get dataReader object

                e57::CompressedVectorReader dataReader = eReader.SetUpData3DPointsData(
                                scanIndex,                      //!< data block index given by the NewData3D
                                nRow,                           //!< size of each of the buffers given
                                xData,                          //!< pointer to a buffer with the x data
                                yData,                          //!< pointer to a buffer with the y data
                                zData,                          //!< pointer to a buffer with the z data
                                isInvalidData,          //!< pointer to a buffer with the valid indication
                                intData,                        //!< pointer to a buffer with the lidar return intesity
                                NULL,
                                redData,                        //!< pointer to a buffer with the color red data
                                greenData,                      //!< pointer to a buffer with the color green data
                                blueData,                       //!< pointer to a buffer with the color blue data
                                NULL,
                                NULL,
                                NULL,
                                NULL,
                                rowIndex,                       //!< pointer to a buffer with the rowIndex
                                columnIndex                     //!< pointer to a buffer with the columnIndex
                                );

Read the point data

                int64_t         count = 0;
                unsigned        size = 0;
                int                     col = 0;
                int                     row = 0;

                while(size = dataReader.read())
                {

Use the data

                        for(long i = 0; i < size; i++)
                        {
                                if(columnIndex)
                                        col = columnIndex[i];
                                else
                                        col = 0;        //point cloud case

                                if(rowIndex)
                                        row = rowIndex[i];
                                else
                                        row = count;    //point cloud case

                                if(isInvalidData[i] == 0)
                                        pScan->SetPoint(row, col, xData[i], yData[i], zData[i]);

                                if(bIntensity){         //Normalize intensity to 0 - 1.
                                        double intensity = (intData[i] - intOffset)/intRange;
                                        pScan->SetIntensity(row, col, intensity);
                                }

                                if(bColor){                     //Normalize color to 0 - 255
                                        int red = ((redData[i] - colorRedOffset) * 255)/colorRedRange;
                                        int green = ((greenData[i] - colorGreenOffset) * 255)/colorBlueRange;
                                        int blue = ((blueData[i] - colorBlueOffset) * 255)/colorBlueRange;
                                        pScan->SetColor(row, col, red, green, blue);

                                count++;
                        }
                }

Close and clean up
                dataReader.close();

                if(isInvalidData) delete isInvalidData;
                if(xData) delete xData;
                if(yData) delete yData;
                if(zData) delete zData;
                if(intData) delete intData;
                if(redData) delete redData;
                if(greenData) delete greenData;
                if(blueData) delete blueData;

/////////////////////////////////////////////////////////////////////
ACCESSING PICTURE IMAGE2D

Get the number of picture images available

                int image2DCount = eReader.GetImage2DCount();

selecting the first picture image

                int imageIndex = 0;

Read the picture 0 header.

                e57::Image2D    imageHeader;
                eReader.ReadImage2D( imageIndex, imageHeader);

Access all the header information

                _bstr_t bstrName = imageHeader.name.c_str();
                _bstr_t bstrGuid = imageHeader.guid.c_str();
                _bstr_t bstrDesc = imageHeader.description.c_str();
                double imageGPSTime = rootHeader.acquisitionDateTime;

Get pose information

                ISI::Point translation;
                translation.x(imageHeader.pose.translation.x);
                translation.y(imageHeader.pose.translation.y);
                translation.z(imageHeader.pose.translation.z);

                ISI::Quat rotation;
                rotation.w(imageHeader.pose.rotation.w);
                rotation.x(imageHeader.pose.rotation.x);
                rotation.y(imageHeader.pose.rotation.y);
                rotation.z(imageHeader.pose.rotation.z);

Get camera information

                _bstr_t bstrSerial = imageHeader.sensorSerialNumber.c_str();
                _bstr_t bstrVendor = imageHeader.sensorVendor.c_str();
                _bstr_t bstrModel = imageHeader.sensorModel.c_str();
                ...

/////////////////////////////////////////////////////////////////////
ACCESSING PICTURE IMAGE

Get the Size of the Picture

                e57::Image2DProjection  imageProjection;        //like E57_SPHERICAL
                e57::Image2DType                imageType;                      //like E57_JPEG_IMAGE
                int64_t                                 nImageWidth = 0;        
                int64_t                                 nImageHeight = 0;
                int64_t                                 nImagesSize = 0;        //Number of bytes in the image
                e57::Image2DType                imageMaskType;          //like E57_PNG_IMAGE_MASK if present
                e57::Image2dType                imageVisualType;        //like E57_JPEG_IMAGE if present

                eReader.GetImage2DSizes( imageIndex, imageProjection, imageType,
                        nImageWidth, nImageHeight, nImagesSize, imageMaskType, imageVisualType);

Get pixel information off the sphericalRepresentation if imageProjection == E57_SPHERICAL

                int32_t imageHeight = imageHeader.sphericalRepresentation.imageHeight;
                int32_t imageWidth = imageHeader.sphericalRepresentation.imageWidth;
                double pixelHeight = imageHeader.sphericalRepresentation.pixelHeight;
                double pixelWidth = imageHeader.sphericalRepresentation.pixelWidth;

Set up buffers

                void* jpegBuffer = new char[nImagesSize];

Read the picture data

                eReader.ReadImage2DData(imageIndex, imageProjection, imageType, jpegBuffer, 0, nImagesSizw);

... access the picture and decode ...

Close and clean up

                delete jpegBuffer;

                eReaer.Close();

/////////////////////////////////////////////////////////////////////
CATCH THE ERRORS

        } catch(E57Exception& ex) {
                ex.report(__FILE__, __LINE__, __FUNCTION__);
        } catch (std::exception& ex) {
                cerr << "Got an std::exception, what=" << ex.what() << endl;
        } catch (...) {
                cerr << "Got an unknown exception" << endl;
        }

Writing using the E57 Simple API

An example of a typical use of this interface would be as follows:

        try
        {

Create a WriterImpl

                _bstr_t bsFile = sFile;                 //converts Unicode to UTF-8
                e57::Writer     eWriter( (char*) bsFile);

                if(!eWriter.IsOpen())                   //test for being open
                        return false;

/////////////////////////////////////////////////////////////
SETTING UP SCAN DATA3D

                e57::Data3D     scanHeader;

Setup the Name and Description

                scanHeader.name = (char*) bstrName;
                scanHeader.description = (char*) bstrDesc;

Setup the GUID

                GUID    guid;                                   //Window's GUID 
                pScan->GetGuid(&guid);
                OLECHAR wbuffer[64];
                StringFromGUID2(guid,&wbuffer[0],64);
                _bstr_t bstrScanGuid = &wbuffer[0];

                scanHeader.guid = (char*) bstrScanGuid;

                scanHeader.acquisitionStart.SetCurrentGPSTime();        //use real time
                scanHeader.acquisitionEnd.SetCurrentGPSTime();

Setup the scan size

                scanHeader.indexBounds.rowMaximum = nRow - 1;   
                scanHeader.indexBounds.rowMinimum = 0;
                scanHeader.indexBounds.columnMaximum = nColumn - 1;
                scanHeader.indexBounds.columnMinimum = 0;
                scanHeader.indexBounds.returnMaximum = 0; 
                scanHeader.indexBounds.returnMinimum = 0;

Setup GroupByLine information

                scanHeader.pointGroupingSchemes.groupingByLine.groupsSize = nColumn;
                scanHeader.pointGroupingSchemes.groupingByLine.pointCountSize = nRow;
                scanHeader.pointGroupingSchemes.groupingByLine.idElementName = "columnIndex";

Set up total number of points

                scanHeader.pointsSize = (nColumn * nRow);

Setup bounds

                if(exportStatistics)                    
                {       //because we are using scaled integers for the data, we must adjust our bounds
                        scanHeader.cartesianBounds.xMaximum = floor(pStat->GetMaxX()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;
                        scanHeader.cartesianBounds.xMinimum = floor(pStat->GetMinX()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;
                        scanHeader.cartesianBounds.yMaximum = floor(pStat->GetMaxY()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;
                        scanHeader.cartesianBounds.yMinimum = floor(pStat->GetMinY()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;
                        scanHeader.cartesianBounds.zMaximum = floor(pStat->GetMaxZ()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;
                        scanHeader.cartesianBounds.zMinimum = floor(pStat->GetMinZ()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;

                        scanHeader.sphericalBounds.rangeMaximum = floor(pStat->GetMaxRange()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;
                        scanHeader.sphericalBounds.rangeMinimum = floor(pStat->GetMinRange()/DATA_SCALE_FACTOR +0.5) * DATA_SCALE_FACTOR;
                        scanHeader.sphericalBounds.azimuthEnd = pStat->GetMaxAzimuth();
                        scanHeader.sphericalBounds.azimuthStart = pStat->GetMinAzimuth();
                        scanHeader.sphericalBounds.elevationMaximum = pStat->GetMaxPolar();
                        scanHeader.sphericalBounds.elevationMinimum = pStat->GetMinPolar();
                }

Setup pose rotation and transformation

                if(exportMatrix)                                
                {
                        scanHeader.pose.rotation.w = rotation.w();
                        scanHeader.pose.rotation.x = rotation.x();
                        scanHeader.pose.rotation.y = rotation.y();
                        scanHeader.pose.rotation.z = rotation.z();
                        scanHeader.pose.translation.x = translation.x();
                        scanHeader.pose.translation.y = translation.y();
                        scanHeader.pose.translation.z = translation.z();
                }

Setup scanner information

                if(exportScanner)
                {
                        scanHeader.sensorSerialNumber = (char*) bstrSerial;
                        scanHeader.sensorVendor = (char*) bstrVendor;
                        scanHeader.sensorModel = (char*) bstrModel;
                        scanHeader.sensorSoftwareVersion = (char*) bstrSoftware;
                        scanHeader.sensorFirmwareVersion = (char*) bstrFirmware;
                        scanHeader.sensorHardwareVersion = (char*) bstrHardware;

                        scanHeader.temperature = pStat->GetTemperature();
                        scanHeader.relativeHumidity = pStat->GetHumidity();
                        scanHeader.atmosphericPressure = pStat->GetAirPressure();
                }
///////////////////////////////////////////////////////////////
SETTING UP PointRecord Fields

Setup Points

                scanHeader.pointFields.cartesianInvalidStateField = true;
                int8_t * isInvalidData = new int8_t[nRow];

                scanHeader.pointFields.cartesianXField = true;
                double * xData = new double[nRow];
                scanHeader.pointFields.cartesianYField = true;
                double * yData = new double[nRow];
                scanHeader.pointFields.cartesianZField = true;
                double * zData = new double[nRow];

                scanHeader.pointFields.pointRangeScaledInteger = DATA_SCALE_FACTOR;
                scanHeader.pointFields.pointRangeMinimum = ((double)-E57_INT32_MAX) / DATA_SCALE_FACTOR;
                scanHeader.pointFields.pointRangeMaximum = ((double) E57_INT32_MAX) / DATA_SCALE_FACTOR;

Setup Color

                uint16_t * redData = NULL;
                uint16_t * greenData = NULL;
                uint16_t * blueData = NULL;
                if(exportColor)
                {
                        scanHeader.pointFields.colorRedField = true;
                        redData = new uint16_t[nRow];
                        scanHeader.pointFields.colorGreenField = true;
                        greenData = new uint16_t[nRow];
                        scanHeader.pointFields.colorBlueField = true;
                        blueData = new uint16_t[nRow];

                        scanheader.colorLimits.colorRedMinimum = e57::E57_UINT8_MIN;
                        scanheader.colorLimits.colorRedMaximum = e57::E57_UINT8_MAX;
                        scanheader.colorLimits.colorGreenMinimum = e57::E57_UINT8_MIN;
                        scanheader.colorLimits.colorGreenMaximum = e57::E57_UINT8_MAX;
                        scanheader.colorLimits.colorBlueMinimum = e57::E57_UINT8_MIN;
                        scanheader.colorLimits.colorBlueMaximum = e57::E57_UINT8_MAX;
                }

Setup Intensity

                double * intData = NULL;
                if(exportIntensity)
                {
                        scanHeader.pointFields.intensityField = true;
                        intData = new double[nRow];

                        header.intensityLimits.intensityMaximum = 1.;
                        headerintensityLimits.intensityMinimum = 0.;
                        header.pointFields.intensityScaledInteger = 0.;         //0. uses FloatNode, -1. uses IntegerNode, >0. uses ScaledIntegerNode
                }

Write out a new scan header and receive back the index

                int scanIndex = eWriter.NewData3D(scanHeader);

Setup the data buffers

                e57::CompressedVectorWriter dataWriter = eWriter.SetUpData3DPointsData(
                                scanIndex,                      //!< data block index given by the NewData3D
                                nRow,                           //!< size of each of the buffers given
                                xData,                          //!< pointer to a buffer with the x data
                                yData,                          //!< pointer to a buffer with the y data
                                zData,                          //!< pointer to a buffer with the z data
                                isInvalidData,          //!< pointer to a buffer with the valid indication
                                intData,                        //!< pointer to a buffer with the lidar return intesity
                                NULL,
                                redData,                        //!< pointer to a buffer with the color red data
                                greenData,                      //!< pointer to a buffer with the color green data
                                blueData,                       //!< pointer to a buffer with the color blue data
                                NULL
                                );

///////////////////////////////////////////////////////////////
WRITING SCAN DATA

                vector<int64_t> idElementValue;
                vector<int64_t> startPointIndex;
                vector<int64_t> pointCount;
                int group = 0;
                int startPoint = 0;

Access the point data

                for(long j = 0; j < nColumn; j++)
                {
                        int count = 0;

                        for(long i = 0; i < nRow; i++)
                        {

Get the invalid status

                                isInvalidData[count] = (pScan->GetStatus(i,j) & INVALID) ? 2 : 0;

Get the point

                                ISI::Point point = pScan->GetPoint(i, j);
                                xData[count] = point.x();
                                yData[count] = point.y();
                                zData[count] = point.z();

Get the intensity 0. to 1. range

                                if(exportIntensity)
                                        intData[count] = pScan->GetIntensity(i, j);

Get the color

                                if(exportColor)
                                {
                                        uint8_t red = 0;
                                        uint8_t green = 0;
                                        uint8_t blue = 0;
                                        pScan->GetColor(i, j, &red, &green, &blue);

                                        redData[count] = (uint8_t) red;
                                        greenData[count] = (uint8_t) green;
                                        blueData[count] = (uint8_t) blue;
                                }
                                count++;
                        }
Write out the buffers

                        dataWriter.write(count);

Collect the group information

                        idElementValue.push_back((int64_t) j);
                        startPointIndex.push_back((int64_t) startPoint);
                        pointCount.push_back((int64_t) count);
                        group++;

                        startPoint += count;
                }

Finish the scan data write

                dataWriter.close();

Write out the group information

                eWriter.WriteData3DGroupsData(scanIndex, group,
                        (int64_t*) &idElementValue[0],
                        (int64_t*) &startPointIndex[0],
                        (int64_t*) &pointCount[0]);

Clean up

                if(isInvalidData) delete isInvalidData;
                if(xData) delete xData;
                if(yData) delete yData;
                if(zData) delete zData;
                if(intData) delete intData;
                if(redData) delete redData;
                if(greenData) delete greenData;
                if(blueData) delete blueData;

/////////////////////////////////////////////////////////////
SETTING UP SCAN IMAGE2D

                e57::Image2D    imageHeader;

Setup the Name and Description

                imageHeader.name = (char*) bstrName;
                imageHeader.description = (char*) bstrDesc;

Setup the GUID

                imageHeader.guid = (char*) bstrImageGuid;
                imageHeader.associatedData3DGuid = (char*) bstrScanGuid;

Setup the DateTime

                imageHeader.acquisitionDateTime.SetCurrentGPSTime() //set current time.

Setup camera information

                imageHeader.sensorSerialNumber = (char*) bstrSerial;
                imageHeader.sensorVendor = (char*) bstrVendor;
                imageHeader.sensorModel = (char*) bstrModel;

Setup image orientation

                imageHeader.pose.rotation.w = rotation.w();
                imageHeader.pose.rotation.x = rotation.x();
                imageHeader.pose.rotation.y = rotation.y();
                imageHeader.pose.rotation.z = rotation.z();
                imageHeader.pose.translation.x = translation.x();
                imageHeader.pose.translation.y = translation.y();
                imageHeader.pose.translation.z = translation.z();

Setup image size

                imageHeader.sphericalRepresentation.imageHeight = imageHeight;
                imageHeader.sphericalRepresentation.imageWidth = imageWidth;
                imageHeader.sphericalRepresentation.pixelHeight = pixelHeight;
                imageHeader.sphericalRepresentation.pixelWidth = pixelWidth;

Open jpeg file

                CFile jpegFile;
                CFileException fileError;
                jpegFile.Open(imagePath, CFile::modeRead | CFile::typeBinary, &fileError);
                ULONGLONG dwLength = jpegFile.GetLength();

                imageHeader.sphericalRepresentation.jpegImageSize = dwLength; //Real Size before newing image header

Write the image header

                int imageIndex = eWriter.NewImage2D(header);

Access the jpeg image data

                void * pBuffer = new char[dwLength];
                jpegFile.SeekToBegin();
                jpegFile.Read(pBuffer,dwLength);

Write the jpeg data

                eWriter.WriteImage2DData(imageIndex, e57::E57_JPEG_IMAGE, e57::E57_SPHERICAL,
                                        pBuffer,0,dwLength);

Finish the E57 file

                eWriter.Close();

/////////////////////////////////////////////////////////////////////
CATCH THE ERRORS

        } catch(E57Exception& ex) {
                ex.report(__FILE__, __LINE__, __FUNCTION__);
        } catch (std::exception& ex) {
                cerr << "Got an std::exception, what=" << ex.what() << endl;
        } catch (...) {
                cerr << "Got an unknown exception" << endl;
        }