Export image

The Export image step saves the converted BitmapImage with additional metadata information into a standard file format.

After the Convert pipeline (see Convert Pipeline) produced a BitmapImage data, one might want to store the result on the file system as part of a delivery, or to further process the image with another application. This step is meant for this use case.

The current version supports the following output formats:

  • Tag Image File Format (TIFF) with GeoTIFF extension

Exporting into Tag Image File Format (TIFF)

To export into TIFF format one must obtain both the original RawImage and the produced BitmapImage along with the TiffConfig configuring the output file.

P1::ImageSdk::RawImage rawImage;
P1::ImageSdk::BitmapImage bitmap;
P1::ImageSdk::TiffConfig config;
std::string filename;

P1::ImageSdk::TiffWriter tiffWriter(filename, bitmap, rawImage, config);
P1.ImageSdk.RawImage rawImage;
P1.ImageSdk.BitmapImage bitmap;
P1.ImageSdk.TiffConfig config;
System.String filename;

rawImage.WriteAsTiff(filename, bitmap, config);

Adding GeoTIFF fields to the metadata

To output a valid GeoTIFF file, the ImageSdk requires a couple of fields to be defined in the TiffConfig structure. A minimum set of required parameters are currently supported.

  • GTRasterTypeGeoKey

  • GTModelTypeGeoKey

  • ModelTiepointTag

  • ModelPixelScaleTag

  • ModelTransformationTag

  • GTCitationGeoKey

See an example of how to add the fields to the configuration.

std::vector< P1::ImageSdk::GeoTiffField > geoTiffFieldList;

// Pixel Scale tag
double pixelScaleArray[3];
if (pixelScaleArray == NULL) return false;
pixelScaleArray[0] = 10.0;  // x
pixelScaleArray[1] = 15.0;  // y
pixelScaleArray[2] = 0.0;   // z
P1::ImageSdk::GeoTiffField pixelScale;
pixelScale.key = P1::ImageSdk::GeoTiffModelPixelScaleTag;
pixelScale.valueType = P1::ImageSdk::GeoTiffValueTypeDouble;
pixelScale.data = pixelScaleArray;
pixelScale.count = 3;
geoTiffFieldList.push_back(pixelScale);

// Tie Point tag
double tiePointArray[6];
tiePointArray[0] = 0.0;   // I (raster space x)
tiePointArray[1] = 5.0;   // J (raster space y)
tiePointArray[2] = 0.0;   // K (pixel value, should be 0)
tiePointArray[3] = 0.0;   // X (model space x)
tiePointArray[4] = 5.0;   // Y (model space y)
tiePointArray[5] = 0.0;   // Z (model space z, should be 0 for 2D model space)
P1::ImageSdk::GeoTiffField tiePoint;
tiePoint.key = P1::ImageSdk::GeoTiffModelTiepointTag;
tiePoint.valueType = P1::ImageSdk::GeoTiffValueTypeDouble;
tiePoint.data = tiePointArray;
tiePoint.count = 6;
geoTiffFieldList.push_back(tiePoint);

// Model Type tag
P1::ImageSdk::GeoTiffField modelType;
modelType.key = P1::ImageSdk::GTModelType;
modelType.valueType = P1::ImageSdk::GeoTiffValueTypeShort;
modelType.count = 0;
modelType.value = 1; // ModelTypeProjected
modelType.data = nullptr;
geoTiffFieldList.push_back(modelType);

// Raster Type tag
P1::ImageSdk::GeoTiffField rasterType;
rasterType.key = P1::ImageSdk::GTRasterType;
rasterType.valueType = P1::ImageSdk::GeoTiffValueTypeShort;
rasterType.count = 0;
rasterType.value = 1; // RasterPixelIsArea
rasterType.data = nullptr;
geoTiffFieldList.push_back(rasterType);

// Citation tag (optional)
char const* citationText = "Test Citation";
auto const citationTextBuffer = (unsigned char*)malloc(strlen(citationText));
if (citationTextBuffer != NULL)
{
    memcpy(citationTextBuffer, citationText, strlen(citationText)); // move the string to the heap so is survives the exiting of the scope

    P1::ImageSdk::GeoTiffField citation;
    citation.key = P1::ImageSdk::GTCitation;
    citation.valueType = P1::ImageSdk::GeoTiffValueTypeAscii;
    citation.data = citationTextBuffer;
    citation.count = strlen(citationText);
    geoTiffFieldList.push_back(citation);
}

P1::ImageSdk::GeoTiffField* const geoTiffFieldListRaw = (P1::ImageSdk::GeoTiffField*)malloc(geoTiffFieldList.size() * sizeof(P1::ImageSdk::GeoTiffField));
if (geoTiffFieldListRaw != NULL)
{
    memcpy(geoTiffFieldListRaw, geoTiffFieldList.data(), geoTiffFieldList.size() * sizeof(GeoTiffField));
    config.commonConfig.geoTiffFieldList = geoTiffFieldListRaw;
    config.commonConfig.geoTiffFieldCount = geoTiffFieldList.size();
}
List<GeoTiffField> geoTiffFieldList = new List<GeoTiffField>();

// Pixel Scale tag
GeoTiffField pixelScale = new GeoTiffField()
{
    key = GeoTiffKey.GeoTiffModelPixelScaleTag,
    doubleArrayValue = new List<double>() { 1.0, 2.5, 0.0 },
};
geoTiffFieldList.Add(pixelScale);

// Tie Point tag
GeoTiffField tiePoint = new GeoTiffField()
{
    key = GeoTiffKey.GeoTiffModelTiepointTag,
    doubleArrayValue = new List<double>() { 0.0, 5.0, 0.0, 1.0, 42.5, 3.14159265 },
};
geoTiffFieldList.Add(tiePoint);

// Model Type tag
GeoTiffField modelType = new GeoTiffField()
{
    key = GeoTiffKey.GTModelType,
    value = 1,
};
geoTiffFieldList.Add(modelType);

// Raster Type tag
GeoTiffField rasterType = new GeoTiffField()
{
    key = GeoTiffKey.GTRasterType,
    value = 1,
};
geoTiffFieldList.Add(rasterType);

// Citation tag (optional)
GeoTiffField citation = new GeoTiffField()
{
    key = GeoTiffKey.GTCitation,
    stringValue = "Test Citation",
};
geoTiffFieldList.Add(citation);

// Add to the configuration        
config.commonConfig.geoTiffFieldList = geoTiffFieldList;