Skip to content

Commit

Permalink
Add GDALRegisterTransformer() to public gdal_alg.h API
Browse files Browse the repository at this point in the history
and convert existing GCP_POLYNOMIAL, GCP_TPS, TPS and GeoLoc
transformers to use it.

This also allows custom spatial point transformers to be registered
and used by GDALCreateGenImgProjTransformer(), and in warped VRT.
  • Loading branch information
rouault committed May 7, 2024
1 parent 24ba421 commit ee9e231
Show file tree
Hide file tree
Showing 8 changed files with 616 additions and 450 deletions.
68 changes: 66 additions & 2 deletions alg/gdal_alg.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,21 +96,83 @@ typedef int (*GDALTransformerFunc)(void *pTransformerArg, int bDstToSrc,
int nPointCount, double *x, double *y,
double *z, int *panSuccess);

/*! @cond Doxygen_Suppress */
/** Signature to be set in GDALTransformerInfo::abySignature member */
#define GDAL_GTI2_SIGNATURE "GTI2"

/** Structure that must be instantiated as the first member of a transformer
* instance.
*/
typedef struct
{
/** Signature. Should be filled with GDAL_GTI2_SIGNATURE. */
GByte abySignature[4];

/** Class name. Should uniquely identify the transformer. */
const char *pszClassName;

/** Transformer callback. */
GDALTransformerFunc pfnTransform;

/** Cleanup callback. */
void (*pfnCleanup)(void *pTransformerArg);

/** XML serialization callback. */
CPLXMLNode *(*pfnSerialize)(void *pTransformerArg);

/** Callback to instanciate a transformer instance similar to the passed one. */
void *(*pfnCreateSimilar)(void *pTransformerArg, double dfSrcRatioX,
double dfSrcRatioY);
} GDALTransformerInfo;

/*! @endcond */
/* Custom transformers */

/** Function pointer that instantiates a transformer instance for use by the
* GDALCreateGenImgProjTransformer() family of functions.
*
* The transformer instance should be a structure whose first member is an
* instance of GDALTransformerInfo.
*
* @param pszMethod Transformation method. May be NULL, in which case the
* callback is free to decide, from the content of the dataset
* and transformer options, if it can be instantiated.
* @param bIsSrcTransformer true if the transformer is used as the source
* transformer of GDALGenImgProjTransform.
* false if the transformer is used as the target
* transformer of GDALGenImgProjTransform.
* @param hDS source or target dataset, depending of bIsSrcTransformer.
* The passed value is not NULL.
* @param papszTransformOptions Transformer options. May be NULL.
* @param[in,out] phSRS Pointer to a OGRSpatialReferenceH. The input *phSRS may be
* set. The callback may assign a new value to *phSRS (to be
* released with OSRRelease(). If the callback needs to free
* the passed *phSRS value, it must do so with OSRRelease().
* @return a new transformer instance, or NULL in case of error or if
* pszMethod == NULL and the callback does not recognize it should be
* instantiated.
*/
typedef void *(*GDALTransformerCreateForGenImgTransformer)(
const char *pszMethod, bool bIsSrcTransformer, GDALDatasetH hDS,
char **papszTransformOptions, OGRSpatialReferenceH *phSRS);

/** Function pointer that takes a XML tree as argument and returns a
* transformer instance.
*
* The transformer instance returned should be a structure whose first member
* is an instance of GDALTransformerInfo.
*
* @param psTree XML tree
* @return a new transformer instance, or NULL in case of error
*/
typedef void *(*GDALTransformDeserializeFunc)(const CPLXMLNode *psTree);

void CPL_DLL *
GDALRegisterTransformer(const char *pszTransformName,
GDALTransformerFunc pfnTransformerFunc,
GDALTransformDeserializeFunc pfnDeserializeFunc,
GDALTransformerCreateForGenImgTransformer
pfnTransformerCreateForGenImgTransformerFunc);

void CPL_DLL GDALUnregisterTransformer(void *pData);

/*! @cond Doxygen_Suppress */
void CPL_DLL GDALDestroyTransformer(void *pTransformerArg);
Expand Down Expand Up @@ -246,6 +308,8 @@ int CPL_DLL GDALApproxTransform(void *pTransformArg, int bDstToSrc,
int nPointCount, double *x, double *y,
double *z, int *panSuccess);

/* Warping related functions */

int CPL_DLL CPL_STDCALL GDALSimpleImageWarp(
GDALDatasetH hSrcDS, GDALDatasetH hDstDS, int nBandCount, int *panBandList,
GDALTransformerFunc pfnTransform, void *pTransformArg,
Expand Down
9 changes: 1 addition & 8 deletions alg/gdal_alg_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,7 @@ constexpr const char *GDAL_GEN_IMG_TRANSFORMER_CLASS_NAME =

bool GDALIsTransformer(void *hTransformerArg, const char *pszClassName);

typedef void *(*GDALTransformDeserializeFunc)(CPLXMLNode *psTree);

void CPL_DLL *GDALRegisterTransformDeserializer(
const char *pszTransformName, GDALTransformerFunc pfnTransformerFunc,
GDALTransformDeserializeFunc pfnDeserializeFunc);
void CPL_DLL GDALUnregisterTransformDeserializer(void *pData);

void GDALCleanupTransformDeserializerMutex();
void GDALCleanupTransformers();

/* Transformer cloning */

Expand Down
9 changes: 5 additions & 4 deletions alg/gdal_crs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,10 @@ struct GCPTransformInfo
volatile int nRefCount{};
};

static CPLXMLNode *GDALSerializeGCPTransformer(void *pTransformArg);

CPL_C_START
CPLXMLNode *GDALSerializeGCPTransformer(void *pTransformArg);
void *GDALDeserializeGCPTransformer(CPLXMLNode *psTree);
void *GDALDeserializeGCPTransformer(const CPLXMLNode *psTree);
CPL_C_END

/* crs.c */
Expand Down Expand Up @@ -501,7 +502,7 @@ CPLXMLNode *GDALSerializeGCPTransformer(void *pTransformArg)
/* GDALDeserializeReprojectionTransformer() */
/************************************************************************/

void *GDALDeserializeGCPTransformer(CPLXMLNode *psTree)
void *GDALDeserializeGCPTransformer(const CPLXMLNode *psTree)

{
std::vector<gdal::GCP> asGCPs;
Expand All @@ -515,7 +516,7 @@ void *GDALDeserializeGCPTransformer(CPLXMLNode *psTree)
/* -------------------------------------------------------------------- */
/* Check for GCPs. */
/* -------------------------------------------------------------------- */
CPLXMLNode *psGCPList = CPLGetXMLNode(psTree, "GCPList");
const CPLXMLNode *psGCPList = CPLGetXMLNode(psTree, "GCPList");

if (psGCPList != nullptr)
{
Expand Down
11 changes: 6 additions & 5 deletions alg/gdal_rpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@

// #define DEBUG_VERBOSE_EXTRACT_DEM

CPL_C_START
CPLXMLNode *GDALSerializeRPCTransformer(void *pTransformArg);
void *GDALDeserializeRPCTransformer(CPLXMLNode *psTree);

CPL_C_START
void *GDALDeserializeRPCTransformer(const CPLXMLNode *psTree);
CPL_C_END

constexpr int MAX_ABS_VALUE_WARNINGS = 20;
Expand Down Expand Up @@ -2326,22 +2327,22 @@ CPLXMLNode *GDALSerializeRPCTransformer(void *pTransformArg)
/* GDALDeserializeRPCTransformer() */
/************************************************************************/

void *GDALDeserializeRPCTransformer(CPLXMLNode *psTree)
void *GDALDeserializeRPCTransformer(const CPLXMLNode *psTree)

{
char **papszOptions = nullptr;

/* -------------------------------------------------------------------- */
/* Collect metadata. */
/* -------------------------------------------------------------------- */
CPLXMLNode *psMetadata = CPLGetXMLNode(psTree, "Metadata");
const CPLXMLNode *psMetadata = CPLGetXMLNode(psTree, "Metadata");

if (psMetadata == nullptr || psMetadata->eType != CXT_Element ||
!EQUAL(psMetadata->pszValue, "Metadata"))
return nullptr;

char **papszMD = nullptr;
for (CPLXMLNode *psMDI = psMetadata->psChild; psMDI != nullptr;
for (const CPLXMLNode *psMDI = psMetadata->psChild; psMDI != nullptr;
psMDI = psMDI->psNext)
{
if (!EQUAL(psMDI->pszValue, "MDI") || psMDI->eType != CXT_Element ||
Expand Down
9 changes: 5 additions & 4 deletions alg/gdal_tps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@
#include "gdal_priv.h"
#include "gdalgenericinverse.h"

static CPLXMLNode *GDALSerializeTPSTransformer(void *pTransformArg);

CPL_C_START
CPLXMLNode *GDALSerializeTPSTransformer(void *pTransformArg);
void *GDALDeserializeTPSTransformer(CPLXMLNode *psTree);
void *GDALDeserializeTPSTransformer(const CPLXMLNode *psTree);
CPL_C_END

struct TPSTransformInfo
Expand Down Expand Up @@ -438,13 +439,13 @@ CPLXMLNode *GDALSerializeTPSTransformer(void *pTransformArg)
/* GDALDeserializeTPSTransformer() */
/************************************************************************/

void *GDALDeserializeTPSTransformer(CPLXMLNode *psTree)
void *GDALDeserializeTPSTransformer(const CPLXMLNode *psTree)

{
/* -------------------------------------------------------------------- */
/* Check for GCPs. */
/* -------------------------------------------------------------------- */
CPLXMLNode *psGCPList = CPLGetXMLNode(psTree, "GCPList");
const CPLXMLNode *psGCPList = CPLGetXMLNode(psTree, "GCPList");

std::vector<gdal::GCP> asGCPs;
if (psGCPList != nullptr)
Expand Down
9 changes: 5 additions & 4 deletions alg/gdalgeoloc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ constexpr float INVALID_BMXY = -10.0f;
#warning "Remove me before committing"
#endif

static CPLXMLNode *GDALSerializeGeoLocTransformer(void *pTransformArg);

CPL_C_START
CPLXMLNode *GDALSerializeGeoLocTransformer(void *pTransformArg);
void *GDALDeserializeGeoLocTransformer(CPLXMLNode *psTree);
void *GDALDeserializeGeoLocTransformer(const CPLXMLNode *psTree);
CPL_C_END

/************************************************************************/
Expand Down Expand Up @@ -2155,13 +2156,13 @@ CPLXMLNode *GDALSerializeGeoLocTransformer(void *pTransformArg)
/* GDALDeserializeGeoLocTransformer() */
/************************************************************************/

void *GDALDeserializeGeoLocTransformer(CPLXMLNode *psTree)
void *GDALDeserializeGeoLocTransformer(const CPLXMLNode *psTree)

{
/* -------------------------------------------------------------------- */
/* Collect metadata. */
/* -------------------------------------------------------------------- */
CPLXMLNode *psMetadata = CPLGetXMLNode(psTree, "Metadata");
const CPLXMLNode *psMetadata = CPLGetXMLNode(psTree, "Metadata");

if (psMetadata == nullptr || psMetadata->eType != CXT_Element ||
!EQUAL(psMetadata->pszValue, "Metadata"))
Expand Down
Loading

0 comments on commit ee9e231

Please sign in to comment.