mirror of
https://github.com/SatDump/SatDump
synced 2026-08-13 17:47:30 -04:00
166 lines
No EOL
6.7 KiB
C++
166 lines
No EOL
6.7 KiB
C++
#include "geotiff.h"
|
|
#include "geotiff_def.h"
|
|
#include <vector>
|
|
|
|
namespace satdump
|
|
{
|
|
namespace geotiff
|
|
{
|
|
bool try_write_geotiff(TIFF *tif, proj::projection_t *proj)
|
|
{
|
|
bool debug = true;
|
|
|
|
// Bunch of checks
|
|
if (proj->type == proj::ProjType_Invalid)
|
|
{
|
|
if (debug)
|
|
printf("Projection is invalid!\n");
|
|
return true;
|
|
}
|
|
|
|
if (!(proj->type == proj::ProjType_Equirectangular || proj->type == proj::ProjType_Stereographic || proj->type == proj::ProjType_UniversalTransverseMercator ||
|
|
proj->type == proj::ProjType_WebMerc))
|
|
{
|
|
if (debug)
|
|
printf("Unsupported projection!\n");
|
|
return true;
|
|
}
|
|
|
|
// Register the tags we need
|
|
char tag_pixelScale[] = "ModelPixelScaleTag";
|
|
// char tag_geoTransform[] = "GeoTransformationMatrix";
|
|
char tag_tiepoint[] = "ModelTiepointTag";
|
|
char tag_geoKeyDirectory[] = "GeoKeyDirectoryTag";
|
|
char tag_geoKeyDoubles[] = "GeoKeysDoubles";
|
|
// char tag_ASCIIParams[] = "GeoASCIIParams";
|
|
|
|
static const TIFFFieldInfo xtiffFieldInfo[] = {
|
|
//
|
|
{GEOTIFFTAG_ModelPixelScaleTag, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, true, true, tag_pixelScale},
|
|
// {TIFFTAG_GEOTRANSMATRIX, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE, tag_geoTransform},
|
|
{GEOTIFFTAG_ModelTiepointTag, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, true, true, tag_tiepoint},
|
|
{GEOTIFFTAG_GeoKeyDirectoryTag, -1, -1, TIFF_SHORT, FIELD_CUSTOM, true, true, tag_geoKeyDirectory},
|
|
{GEOTIFFTAG_GeoKeysDoubles, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, true, true, tag_geoKeyDoubles},
|
|
// {TIFFTAG_GEOASCIIPARAMS, -1, -1, TIFF_ASCII, FIELD_CUSTOM, TRUE, FALSE, tag_ASCIIParams}
|
|
//
|
|
};
|
|
#define N(a) (sizeof(a) / sizeof(a[0]))
|
|
TIFFMergeFieldInfo(tif, xtiffFieldInfo, N(xtiffFieldInfo));
|
|
|
|
// Start by writing tiepoints
|
|
double tiepoints[6] = {0.0, 0.0, 0.0, proj->proj_offset_x, proj->proj_offset_y, 0.0};
|
|
TIFFSetField(tif, GEOTIFFTAG_ModelTiepointTag, 6, &tiepoints);
|
|
|
|
// Then write pixel scales
|
|
double pixelscales[3] = {proj->proj_scalar_x, -proj->proj_scalar_y, 0.0};
|
|
TIFFSetField(tif, GEOTIFFTAG_ModelPixelScaleTag, 3, &pixelscales);
|
|
|
|
// Finally, the GeoKeys
|
|
std::vector<uint16_t> geoskeys(4);
|
|
geoskeys[0] = 1; // KeyDirectoryVersion
|
|
geoskeys[1] = 1; // KeyRevision
|
|
geoskeys[2] = 0; // MinorRevision
|
|
geoskeys[3] = 0; // NumberOfKeys
|
|
|
|
std::vector<double> doublekeys;
|
|
int keysn = 0;
|
|
{
|
|
// Model Type
|
|
geoskeys.push_back(GTModelTypeGeoKey);
|
|
geoskeys.push_back(0);
|
|
geoskeys.push_back(1);
|
|
if (proj->type == proj::ProjType_Equirectangular)
|
|
geoskeys.push_back(ModelTypeGeographic);
|
|
else
|
|
geoskeys.push_back(ModelTypeProjected);
|
|
keysn++;
|
|
|
|
// Projected model type
|
|
if (proj->type == proj::ProjType_UniversalTransverseMercator)
|
|
{ // UTM Mercator
|
|
int value = 0;
|
|
|
|
printf("ZONE IS %d\n", proj->params.zone);
|
|
if (proj->params.south)
|
|
value = PCS_WGS84_UTM_zone_1S - 1 + proj->params.zone;
|
|
else
|
|
value = PCS_WGS84_UTM_zone_1N - 1 + proj->params.zone;
|
|
|
|
geoskeys.push_back(ProjectedCSTypeGeoKey);
|
|
geoskeys.push_back(0);
|
|
geoskeys.push_back(1);
|
|
geoskeys.push_back(value);
|
|
keysn++;
|
|
}
|
|
else if (proj->type == proj::ProjType_Stereographic)
|
|
{ // Stereographic
|
|
geoskeys.push_back(ProjCoordTransGeoKey);
|
|
geoskeys.push_back(0);
|
|
geoskeys.push_back(1);
|
|
geoskeys.push_back(CT_Stereographic);
|
|
keysn++;
|
|
}
|
|
else if (proj->type == proj::ProjType_WebMerc)
|
|
{
|
|
geoskeys.push_back(ProjectedCSTypeGeoKey);
|
|
geoskeys.push_back(0);
|
|
geoskeys.push_back(1);
|
|
geoskeys.push_back(3857);
|
|
keysn++;
|
|
}
|
|
|
|
// Longitude/Latitude of origin
|
|
if (proj->lam0 != 0)
|
|
{ // Longitude is not 0
|
|
doublekeys.push_back(proj->lam0 * RAD2DEG);
|
|
geoskeys.push_back(ProjCenterLongGeoKey);
|
|
geoskeys.push_back(GEOTIFFTAG_GeoKeysDoubles);
|
|
geoskeys.push_back(1);
|
|
geoskeys.push_back(doublekeys.size() - 1);
|
|
keysn++;
|
|
}
|
|
if (proj->phi0 != 0)
|
|
{ // Latitude is not 0
|
|
doublekeys.push_back(proj->phi0 * RAD2DEG);
|
|
geoskeys.push_back(ProjCenterLatGeoKey);
|
|
geoskeys.push_back(GEOTIFFTAG_GeoKeysDoubles);
|
|
geoskeys.push_back(1);
|
|
geoskeys.push_back(doublekeys.size() - 1);
|
|
keysn++;
|
|
}
|
|
|
|
// Angular unit. Always degree for us
|
|
if (proj->type == proj::ProjType_Equirectangular || proj->lam0 != 0 || proj->phi0 != 0)
|
|
{
|
|
geoskeys.push_back(GeogAngularUnitsGeoKey);
|
|
geoskeys.push_back(0);
|
|
geoskeys.push_back(1);
|
|
geoskeys.push_back(Angular_Degree);
|
|
keysn++;
|
|
}
|
|
|
|
// Ellipsoid model. Always WGS84 for us!
|
|
{
|
|
geoskeys.push_back(GeographicTypeGeoKey);
|
|
geoskeys.push_back(0);
|
|
geoskeys.push_back(1);
|
|
geoskeys.push_back(GCS_WGS_84);
|
|
keysn++;
|
|
}
|
|
}
|
|
|
|
geoskeys[3] = keysn;
|
|
|
|
uint16_t *geokeys_ptr = geoskeys.data();
|
|
TIFFSetField(tif, GEOTIFFTAG_GeoKeyDirectoryTag, geoskeys.size(), geokeys_ptr);
|
|
|
|
if (doublekeys.size() > 0)
|
|
{
|
|
double *doublekeys_ptr = doublekeys.data();
|
|
TIFFSetField(tif, GEOTIFFTAG_GeoKeysDoubles, doublekeys.size(), doublekeys_ptr);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
} // namespace geotiff
|
|
} // namespace satdump
|