mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
.gdal moved to bazaar
git-svn-id: svn://ultimatepp.org/upp/trunk@9273 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
91d7449c7b
commit
23ff1e7e82
2535 changed files with 1272044 additions and 0 deletions
51
bazaar/plugin/gdal/alg/GNUmakefile
Normal file
51
bazaar/plugin/gdal/alg/GNUmakefile
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
include ../GDALmake.opt
|
||||
|
||||
OBJ = gdalmediancut.o gdaldither.o gdal_crs.o gdaltransformer.o \
|
||||
gdalsimplewarp.o gdalwarper.o gdalwarpkernel.o \
|
||||
gdalwarpoperation.o gdalchecksum.o gdal_rpc.o gdal_tps.o \
|
||||
thinplatespline.o llrasterize.o gdalrasterize.o gdalgeoloc.o \
|
||||
gdalgrid.o gdalcutline.o gdalproximity.o rasterfill.o \
|
||||
gdalrasterpolygonenumerator.o \
|
||||
gdalsievefilter.o gdalwarpkernel_opencl.o polygonize.o \
|
||||
gdalrasterfpolygonenumerator.o fpolygonize.o \
|
||||
contour.o gdaltransformgeolocs.o \
|
||||
gdal_octave.o gdal_simplesurf.o gdalmatching.o
|
||||
|
||||
ifeq ($(HAVE_AVX_AT_COMPILE_TIME),yes)
|
||||
CPPFLAGS := -DHAVE_AVX_AT_COMPILE_TIME $(CPPFLAGS)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SSE_AT_COMPILE_TIME),yes)
|
||||
CPPFLAGS := -DHAVE_SSE_AT_COMPILE_TIME $(CPPFLAGS)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_GEOS),yes)
|
||||
CPPFLAGS := -DHAVE_GEOS=1 $(GEOS_CFLAGS) $(CPPFLAGS)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_ARMADILLO),yes)
|
||||
CPPFLAGS := -DHAVE_ARMADILLO $(CPPFLAGS)
|
||||
endif
|
||||
|
||||
CPPFLAGS := $(CPPFLAGS) $(OPENCL_FLAGS)
|
||||
|
||||
default: $(OBJ:.o=.$(OBJ_EXT)) gdalgridavx.$(OBJ_EXT) gdalgridsse.$(OBJ_EXT)
|
||||
|
||||
gdalgridavx.$(OBJ_EXT): gdalgridavx.cpp
|
||||
$(CXX) $(GDAL_INCLUDE) $(CXXFLAGS) $(AVXFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||
|
||||
gdalgridsse.$(OBJ_EXT): gdalgridsse.cpp
|
||||
$(CXX) $(GDAL_INCLUDE) $(CXXFLAGS) $(SSEFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o $(O_OBJ)
|
||||
|
||||
docs:
|
||||
(cd ..; $(MAKE) docs)
|
||||
|
||||
install:
|
||||
for f in *.h ; do $(INSTALL_DATA) $$f $(DESTDIR)$(INST_INCLUDE) ; done
|
||||
|
||||
lib: $(OBJ:.o=.$(OBJ_EXT))
|
||||
(cd .. ; $(MAKE) force-lib)
|
||||
1627
bazaar/plugin/gdal/alg/contour.cpp
Normal file
1627
bazaar/plugin/gdal/alg/contour.cpp
Normal file
File diff suppressed because it is too large
Load diff
820
bazaar/plugin/gdal/alg/fpolygonize.cpp
Normal file
820
bazaar/plugin/gdal/alg/fpolygonize.cpp
Normal file
|
|
@ -0,0 +1,820 @@
|
|||
/******************************************************************************
|
||||
* $Id: fpolygonize.cpp 22501 2011-06-04 21:28:47Z rouault $
|
||||
*
|
||||
* Project: GDAL
|
||||
* Purpose: Version of Raster to Polygon Converter using float buffers.
|
||||
* Author: Jorge Arevalo, jorge.arevalo@deimos-space.com. Most of the code
|
||||
* taken from GDALPolygonize.cpp, by Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2011, Jorge Arevalo
|
||||
* Copyright (c) 2008, Frank Warmerdam
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_alg_priv.h"
|
||||
#include "cpl_conv.h"
|
||||
#include "cpl_string.h"
|
||||
#include <vector>
|
||||
|
||||
CPL_CVSID("$Id: fpolygonize.cpp 22501 2011-06-04 21:28:47Z rouault $");
|
||||
|
||||
#define GP_NODATA_MARKER -51502112
|
||||
|
||||
#ifdef OGR_ENABLED
|
||||
|
||||
/******************************************************************************/
|
||||
/* GDALFloatEquals() */
|
||||
/* Code from: */
|
||||
/* http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm */
|
||||
/******************************************************************************/
|
||||
GBool GDALFloatEquals(float A, float B)
|
||||
{
|
||||
/**
|
||||
* This function will allow maxUlps-1 floats between A and B.
|
||||
*/
|
||||
int maxUlps = MAX_ULPS;
|
||||
int aInt, bInt;
|
||||
|
||||
/**
|
||||
* Make sure maxUlps is non-negative and small enough that the default NAN
|
||||
* won't compare as equal to anything.
|
||||
*/
|
||||
CPLAssert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024);
|
||||
|
||||
/**
|
||||
* This assignation could violate strict aliasing. It causes a warning with
|
||||
* gcc -O2. Use of memcpy preferred. Credits for Even Rouault. Further info
|
||||
* at http://trac.osgeo.org/gdal/ticket/4005#comment:6
|
||||
*/
|
||||
//int aInt = *(int*)&A;
|
||||
memcpy(&aInt, &A, 4);
|
||||
|
||||
/**
|
||||
* Make aInt lexicographically ordered as a twos-complement int
|
||||
*/
|
||||
if (aInt < 0)
|
||||
aInt = 0x80000000 - aInt;
|
||||
/**
|
||||
* Make bInt lexicographically ordered as a twos-complement int
|
||||
*/
|
||||
//int bInt = *(int*)&B;
|
||||
memcpy(&bInt, &B, 4);
|
||||
|
||||
if (bInt < 0)
|
||||
bInt = 0x80000000 - bInt;
|
||||
int intDiff = abs(aInt - bInt);
|
||||
if (intDiff <= maxUlps)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* RPolygonF */
|
||||
/* */
|
||||
/* This is a helper class to hold polygons while they are being */
|
||||
/* formed in memory, and to provide services to coalesce a much */
|
||||
/* of edge sections into complete rings. */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
class RPolygonF {
|
||||
public:
|
||||
RPolygonF( float fValue ) { fPolyValue = fValue; nLastLineUpdated = -1; }
|
||||
|
||||
float fPolyValue;
|
||||
int nLastLineUpdated;
|
||||
|
||||
std::vector< std::vector<int> > aanXY;
|
||||
|
||||
void AddSegment( int x1, int y1, int x2, int y2 );
|
||||
void Dump();
|
||||
void Coalesce();
|
||||
void Merge( int iBaseString, int iSrcString, int iDirection );
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* Dump() */
|
||||
/************************************************************************/
|
||||
void RPolygonF::Dump()
|
||||
{
|
||||
size_t iString;
|
||||
|
||||
printf( "RPolygonF: Value=%f, LastLineUpdated=%d\n",
|
||||
fPolyValue, nLastLineUpdated );
|
||||
|
||||
for( iString = 0; iString < aanXY.size(); iString++ )
|
||||
{
|
||||
std::vector<int> &anString = aanXY[iString];
|
||||
size_t iVert;
|
||||
|
||||
printf( " String %d:\n", (int) iString );
|
||||
for( iVert = 0; iVert < anString.size(); iVert += 2 )
|
||||
{
|
||||
printf( " (%d,%d)\n", anString[iVert], anString[iVert+1] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Coalesce() */
|
||||
/************************************************************************/
|
||||
|
||||
void RPolygonF::Coalesce()
|
||||
|
||||
{
|
||||
size_t iBaseString;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Iterate over loops starting from the first, trying to merge */
|
||||
/* other segments into them. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( iBaseString = 0; iBaseString < aanXY.size(); iBaseString++ )
|
||||
{
|
||||
std::vector<int> &anBase = aanXY[iBaseString];
|
||||
int bMergeHappened = TRUE;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Keep trying to merge the following strings into our target */
|
||||
/* "base" string till we have tried them all once without any */
|
||||
/* mergers. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
while( bMergeHappened )
|
||||
{
|
||||
size_t iString;
|
||||
|
||||
bMergeHappened = FALSE;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Loop over the following strings, trying to find one we can */
|
||||
/* merge onto the end of our base string. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( iString = iBaseString+1;
|
||||
iString < aanXY.size();
|
||||
iString++ )
|
||||
{
|
||||
std::vector<int> &anString = aanXY[iString];
|
||||
|
||||
if( anBase[anBase.size()-2] == anString[0]
|
||||
&& anBase[anBase.size()-1] == anString[1] )
|
||||
{
|
||||
Merge( iBaseString, iString, 1 );
|
||||
bMergeHappened = TRUE;
|
||||
}
|
||||
else if( anBase[anBase.size()-2] == anString[anString.size()-2]
|
||||
&& anBase[anBase.size()-1] == anString[anString.size()-1] )
|
||||
{
|
||||
Merge( iBaseString, iString, -1 );
|
||||
bMergeHappened = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point our loop *should* be closed! */
|
||||
|
||||
CPLAssert( anBase[0] == anBase[anBase.size()-2]
|
||||
&& anBase[1] == anBase[anBase.size()-1] );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Merge() */
|
||||
/************************************************************************/
|
||||
|
||||
void RPolygonF::Merge( int iBaseString, int iSrcString, int iDirection )
|
||||
|
||||
{
|
||||
std::vector<int> &anBase = aanXY[iBaseString];
|
||||
std::vector<int> &anString = aanXY[iSrcString];
|
||||
int iStart, iEnd, i;
|
||||
|
||||
if( iDirection == 1 )
|
||||
{
|
||||
iStart = 1;
|
||||
iEnd = anString.size() / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
iStart = anString.size() / 2 - 2;
|
||||
iEnd = -1;
|
||||
}
|
||||
|
||||
for( i = iStart; i != iEnd; i += iDirection )
|
||||
{
|
||||
anBase.push_back( anString[i*2+0] );
|
||||
anBase.push_back( anString[i*2+1] );
|
||||
}
|
||||
|
||||
if( iSrcString < ((int) aanXY.size())-1 )
|
||||
aanXY[iSrcString] = aanXY[aanXY.size()-1];
|
||||
|
||||
size_t nSize = aanXY.size();
|
||||
aanXY.resize(nSize-1);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* AddSegment() */
|
||||
/************************************************************************/
|
||||
|
||||
void RPolygonF::AddSegment( int x1, int y1, int x2, int y2 )
|
||||
|
||||
{
|
||||
nLastLineUpdated = MAX(y1, y2);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Is there an existing string ending with this? */
|
||||
/* -------------------------------------------------------------------- */
|
||||
size_t iString;
|
||||
|
||||
for( iString = 0; iString < aanXY.size(); iString++ )
|
||||
{
|
||||
std::vector<int> &anString = aanXY[iString];
|
||||
size_t nSSize = anString.size();
|
||||
|
||||
if( anString[nSSize-2] == x1
|
||||
&& anString[nSSize-1] == y1 )
|
||||
{
|
||||
int nTemp;
|
||||
|
||||
nTemp = x2;
|
||||
x2 = x1;
|
||||
x1 = nTemp;
|
||||
|
||||
nTemp = y2;
|
||||
y2 = y1;
|
||||
y1 = nTemp;
|
||||
}
|
||||
|
||||
if( anString[nSSize-2] == x2
|
||||
&& anString[nSSize-1] == y2 )
|
||||
{
|
||||
// We are going to add a segment, but should we just extend
|
||||
// an existing segment already going in the right direction?
|
||||
|
||||
int nLastLen = MAX(ABS(anString[nSSize-4]-anString[nSSize-2]),
|
||||
ABS(anString[nSSize-3]-anString[nSSize-1]));
|
||||
|
||||
if( nSSize >= 4
|
||||
&& (anString[nSSize-4] - anString[nSSize-2]
|
||||
== (anString[nSSize-2] - x1)*nLastLen)
|
||||
&& (anString[nSSize-3] - anString[nSSize-1]
|
||||
== (anString[nSSize-1] - y1)*nLastLen) )
|
||||
{
|
||||
anString.pop_back();
|
||||
anString.pop_back();
|
||||
}
|
||||
|
||||
anString.push_back( x1 );
|
||||
anString.push_back( y1 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create a new string. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
size_t nSize = aanXY.size();
|
||||
aanXY.resize(nSize + 1);
|
||||
std::vector<int> &anString = aanXY[nSize];
|
||||
|
||||
anString.push_back( x1 );
|
||||
anString.push_back( y1 );
|
||||
anString.push_back( x2 );
|
||||
anString.push_back( y2 );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* End of RPolygonF */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
/************************************************************************/
|
||||
/* AddEdges() */
|
||||
/* */
|
||||
/* Examine one pixel and compare to its neighbour above */
|
||||
/* (previous) and right. If they are different polygon ids */
|
||||
/* then add the pixel edge to this polygon and the one on the */
|
||||
/* other side of the edge. */
|
||||
/************************************************************************/
|
||||
|
||||
static void AddEdges( GInt32 *panThisLineId, GInt32 *panLastLineId,
|
||||
GInt32 *panPolyIdMap, float *pafPolyValue,
|
||||
RPolygonF **papoPoly, int iX, int iY )
|
||||
|
||||
{
|
||||
int nThisId = panThisLineId[iX];
|
||||
int nRightId = panThisLineId[iX+1];
|
||||
int nPreviousId = panLastLineId[iX];
|
||||
int iXReal = iX - 1;
|
||||
|
||||
if( nThisId != -1 )
|
||||
nThisId = panPolyIdMap[nThisId];
|
||||
if( nRightId != -1 )
|
||||
nRightId = panPolyIdMap[nRightId];
|
||||
if( nPreviousId != -1 )
|
||||
nPreviousId = panPolyIdMap[nPreviousId];
|
||||
|
||||
if( nThisId != nPreviousId )
|
||||
{
|
||||
if( nThisId != -1 )
|
||||
{
|
||||
if( papoPoly[nThisId] == NULL )
|
||||
papoPoly[nThisId] = new RPolygonF( pafPolyValue[nThisId] );
|
||||
|
||||
papoPoly[nThisId]->AddSegment( iXReal, iY, iXReal+1, iY );
|
||||
}
|
||||
if( nPreviousId != -1 )
|
||||
{
|
||||
if( papoPoly[nPreviousId] == NULL )
|
||||
papoPoly[nPreviousId] = new RPolygonF(pafPolyValue[nPreviousId]);
|
||||
|
||||
papoPoly[nPreviousId]->AddSegment( iXReal, iY, iXReal+1, iY );
|
||||
}
|
||||
}
|
||||
|
||||
if( nThisId != nRightId )
|
||||
{
|
||||
if( nThisId != -1 )
|
||||
{
|
||||
if( papoPoly[nThisId] == NULL )
|
||||
papoPoly[nThisId] = new RPolygonF(pafPolyValue[nThisId]);
|
||||
|
||||
papoPoly[nThisId]->AddSegment( iXReal+1, iY, iXReal+1, iY+1 );
|
||||
}
|
||||
|
||||
if( nRightId != -1 )
|
||||
{
|
||||
if( papoPoly[nRightId] == NULL )
|
||||
papoPoly[nRightId] = new RPolygonF(pafPolyValue[nRightId]);
|
||||
|
||||
papoPoly[nRightId]->AddSegment( iXReal+1, iY, iXReal+1, iY+1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* EmitPolygonToLayer() */
|
||||
/************************************************************************/
|
||||
|
||||
static CPLErr
|
||||
EmitPolygonToLayer( OGRLayerH hOutLayer, int iPixValField,
|
||||
RPolygonF *poRPoly, double *padfGeoTransform )
|
||||
|
||||
{
|
||||
OGRFeatureH hFeat;
|
||||
OGRGeometryH hPolygon;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Turn bits of lines into coherent rings. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poRPoly->Coalesce();
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create the polygon geometry. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
size_t iString;
|
||||
|
||||
hPolygon = OGR_G_CreateGeometry( wkbPolygon );
|
||||
|
||||
for( iString = 0; iString < poRPoly->aanXY.size(); iString++ )
|
||||
{
|
||||
std::vector<int> &anString = poRPoly->aanXY[iString];
|
||||
OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing );
|
||||
|
||||
int iVert;
|
||||
|
||||
// we go last to first to ensure the linestring is allocated to
|
||||
// the proper size on the first try.
|
||||
for( iVert = anString.size()/2 - 1; iVert >= 0; iVert-- )
|
||||
{
|
||||
double dfX, dfY;
|
||||
int nPixelX, nPixelY;
|
||||
|
||||
nPixelX = anString[iVert*2];
|
||||
nPixelY = anString[iVert*2+1];
|
||||
|
||||
dfX = padfGeoTransform[0]
|
||||
+ nPixelX * padfGeoTransform[1]
|
||||
+ nPixelY * padfGeoTransform[2];
|
||||
dfY = padfGeoTransform[3]
|
||||
+ nPixelX * padfGeoTransform[4]
|
||||
+ nPixelY * padfGeoTransform[5];
|
||||
|
||||
OGR_G_SetPoint_2D( hRing, iVert, dfX, dfY );
|
||||
}
|
||||
|
||||
OGR_G_AddGeometryDirectly( hPolygon, hRing );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create the feature object. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
hFeat = OGR_F_Create( OGR_L_GetLayerDefn( hOutLayer ) );
|
||||
|
||||
OGR_F_SetGeometryDirectly( hFeat, hPolygon );
|
||||
|
||||
if( iPixValField >= 0 )
|
||||
OGR_F_SetFieldDouble( hFeat, iPixValField, (double)poRPoly->fPolyValue );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Write the to the layer. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLErr eErr = CE_None;
|
||||
|
||||
if( OGR_L_CreateFeature( hOutLayer, hFeat ) != OGRERR_NONE )
|
||||
eErr = CE_Failure;
|
||||
|
||||
OGR_F_Destroy( hFeat );
|
||||
|
||||
return eErr;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GPMaskImageData() */
|
||||
/* */
|
||||
/* Mask out image pixels to a special nodata value if the mask */
|
||||
/* band is zero. */
|
||||
/************************************************************************/
|
||||
|
||||
static CPLErr
|
||||
GPMaskImageData( GDALRasterBandH hMaskBand, GByte* pabyMaskLine, int iY, int nXSize,
|
||||
float *pafImageLine )
|
||||
|
||||
{
|
||||
CPLErr eErr;
|
||||
|
||||
eErr = GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1,
|
||||
pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0 );
|
||||
if( eErr == CE_None )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < nXSize; i++ )
|
||||
{
|
||||
if( pabyMaskLine[i] == 0 )
|
||||
pafImageLine[i] = GP_NODATA_MARKER;
|
||||
}
|
||||
}
|
||||
|
||||
return eErr;
|
||||
}
|
||||
#endif // OGR_ENABLED
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALFPolygonize() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Create polygon coverage from raster data.
|
||||
*
|
||||
* This function creates vector polygons for all connected regions of pixels in
|
||||
* the raster sharing a common pixel value. Optionally each polygon may be
|
||||
* labelled with the pixel value in an attribute. Optionally a mask band
|
||||
* can be provided to determine which pixels are eligible for processing.
|
||||
*
|
||||
* The source pixel band values are read into a 32bit float buffer. If you want
|
||||
* to use a (probably faster) version using signed 32bit integer buffer, see
|
||||
* GDALPolygonize() at polygonize.cpp.
|
||||
*
|
||||
* Polygon features will be created on the output layer, with polygon
|
||||
* geometries representing the polygons. The polygon geometries will be
|
||||
* in the georeferenced coordinate system of the image (based on the
|
||||
* geotransform of the source dataset). It is acceptable for the output
|
||||
* layer to already have features. Note that GDALFPolygonize() does not
|
||||
* set the coordinate system on the output layer. Application code should
|
||||
* do this when the layer is created, presumably matching the raster
|
||||
* coordinate system.
|
||||
*
|
||||
* The algorithm used attempts to minimize memory use so that very large
|
||||
* rasters can be processed. However, if the raster has many polygons
|
||||
* or very large/complex polygons, the memory use for holding polygon
|
||||
* enumerations and active polygon geometries may grow to be quite large.
|
||||
*
|
||||
* The algorithm will generally produce very dense polygon geometries, with
|
||||
* edges that follow exactly on pixel boundaries for all non-interior pixels.
|
||||
* For non-thematic raster data (such as satellite images) the result will
|
||||
* essentially be one small polygon per pixel, and memory and output layer
|
||||
* sizes will be substantial. The algorithm is primarily intended for
|
||||
* relatively simple thematic imagery, masks, and classification results.
|
||||
*
|
||||
* @param hSrcBand the source raster band to be processed.
|
||||
* @param hMaskBand an optional mask band. All pixels in the mask band with a
|
||||
* value other than zero will be considered suitable for collection as
|
||||
* polygons.
|
||||
* @param hOutLayer the vector feature layer to which the polygons should
|
||||
* be written.
|
||||
* @param iPixValField the attribute field index indicating the feature
|
||||
* attribute into which the pixel value of the polygon should be written.
|
||||
* @param papszOptions a name/value list of additional options
|
||||
* <dl>
|
||||
* <dt>"8CONNECTED":</dt> May be set to "8" to use 8 connectedness.
|
||||
* Otherwise 4 connectedness will be applied to the algorithm
|
||||
* </dl>
|
||||
* @param pfnProgress callback for reporting algorithm progress matching the
|
||||
* GDALProgressFunc() semantics. May be NULL.
|
||||
* @param pProgressArg callback argument passed to pfnProgress.
|
||||
*
|
||||
* @return CE_None on success or CE_Failure on a failure.
|
||||
*
|
||||
* @since GDAL 1.9.0
|
||||
*/
|
||||
|
||||
CPLErr CPL_STDCALL
|
||||
GDALFPolygonize( GDALRasterBandH hSrcBand,
|
||||
GDALRasterBandH hMaskBand,
|
||||
OGRLayerH hOutLayer, int iPixValField,
|
||||
char **papszOptions,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg )
|
||||
|
||||
{
|
||||
#ifndef OGR_ENABLED
|
||||
CPLError(CE_Failure, CPLE_NotSupported, "GDALFPolygonize() unimplemented in a non OGR build");
|
||||
return CE_Failure;
|
||||
#else
|
||||
VALIDATE_POINTER1( hSrcBand, "GDALFPolygonize", CE_Failure );
|
||||
VALIDATE_POINTER1( hOutLayer, "GDALFPolygonize", CE_Failure );
|
||||
|
||||
if( pfnProgress == NULL )
|
||||
pfnProgress = GDALDummyProgress;
|
||||
|
||||
int nConnectedness = CSLFetchNameValue( papszOptions, "8CONNECTED" ) ? 8 : 4;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Confirm our output layer will support feature creation. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( !OGR_L_TestCapability( hOutLayer, OLCSequentialWrite ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Output feature layer does not appear to support creation\n"
|
||||
"of features in GDALFPolygonize()." );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Allocate working buffers. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLErr eErr = CE_None;
|
||||
int nXSize = GDALGetRasterBandXSize( hSrcBand );
|
||||
int nYSize = GDALGetRasterBandYSize( hSrcBand );
|
||||
float *pafLastLineVal = (float *) VSIMalloc2(sizeof(float),nXSize + 2);
|
||||
float *pafThisLineVal = (float *) VSIMalloc2(sizeof(float),nXSize + 2);
|
||||
GInt32 *panLastLineId = (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
|
||||
GInt32 *panThisLineId = (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
|
||||
GByte *pabyMaskLine = (hMaskBand != NULL) ? (GByte *) VSIMalloc(nXSize) : NULL;
|
||||
if (pafLastLineVal == NULL || pafThisLineVal == NULL ||
|
||||
panLastLineId == NULL || panThisLineId == NULL ||
|
||||
(hMaskBand != NULL && pabyMaskLine == NULL))
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_OutOfMemory,
|
||||
"Could not allocate enough memory for temporary buffers");
|
||||
CPLFree( panThisLineId );
|
||||
CPLFree( panLastLineId );
|
||||
CPLFree( pafThisLineVal );
|
||||
CPLFree( pafLastLineVal );
|
||||
CPLFree( pabyMaskLine );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Get the geotransform, if there is one, so we can convert the */
|
||||
/* vectors into georeferenced coordinates. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GDALDatasetH hSrcDS = GDALGetBandDataset( hSrcBand );
|
||||
double adfGeoTransform[6] = { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 };
|
||||
|
||||
if( hSrcDS )
|
||||
GDALGetGeoTransform( hSrcDS, adfGeoTransform );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* The first pass over the raster is only used to build up the */
|
||||
/* polygon id map so we will know in advance what polygons are */
|
||||
/* what on the second pass. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int iY;
|
||||
GDALRasterFPolygonEnumerator oFirstEnum(nConnectedness);
|
||||
|
||||
for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
|
||||
{
|
||||
eErr = GDALRasterIO(
|
||||
hSrcBand,
|
||||
GF_Read, 0, iY, nXSize, 1,
|
||||
pafThisLineVal, nXSize, 1, GDT_Float32, 0, 0 );
|
||||
|
||||
if( eErr == CE_None && hMaskBand != NULL )
|
||||
eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize,
|
||||
pafThisLineVal );
|
||||
|
||||
if( iY == 0 )
|
||||
oFirstEnum.ProcessLine(
|
||||
NULL, pafThisLineVal, NULL, panThisLineId, nXSize );
|
||||
else
|
||||
oFirstEnum.ProcessLine(
|
||||
pafLastLineVal, pafThisLineVal,
|
||||
panLastLineId, panThisLineId,
|
||||
nXSize );
|
||||
|
||||
// swap lines
|
||||
float * pafTmp = pafLastLineVal;
|
||||
pafLastLineVal = pafThisLineVal;
|
||||
pafThisLineVal = pafTmp;
|
||||
|
||||
GInt32 * panTmp = panThisLineId;
|
||||
panThisLineId = panLastLineId;
|
||||
panLastLineId = panTmp;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Report progress, and support interrupts. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( eErr == CE_None
|
||||
&& !pfnProgress( 0.10 * ((iY+1) / (double) nYSize),
|
||||
"", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
eErr = CE_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Make a pass through the maps, ensuring every polygon id */
|
||||
/* points to the final id it should use, not an intermediate */
|
||||
/* value. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
oFirstEnum.CompleteMerges();
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Initialize ids to -1 to serve as a nodata value for the */
|
||||
/* previous line, and past the beginning and end of the */
|
||||
/* scanlines. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int iX;
|
||||
|
||||
panThisLineId[0] = -1;
|
||||
panThisLineId[nXSize+1] = -1;
|
||||
|
||||
for( iX = 0; iX < nXSize+2; iX++ )
|
||||
panLastLineId[iX] = -1;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* We will use a new enumerator for the second pass primariliy */
|
||||
/* so we can preserve the first pass map. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GDALRasterFPolygonEnumerator oSecondEnum(nConnectedness);
|
||||
RPolygonF **papoPoly = (RPolygonF **)
|
||||
CPLCalloc(sizeof(RPolygonF*),oFirstEnum.nNextPolygonId);
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Second pass during which we will actually collect polygon */
|
||||
/* edges as geometries. */
|
||||
/* ==================================================================== */
|
||||
for( iY = 0; eErr == CE_None && iY < nYSize+1; iY++ )
|
||||
{
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read the image data. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( iY < nYSize )
|
||||
{
|
||||
eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1,
|
||||
pafThisLineVal, nXSize, 1, GDT_Float32, 0, 0 );
|
||||
|
||||
if( eErr == CE_None && hMaskBand != NULL )
|
||||
eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize,
|
||||
pafThisLineVal );
|
||||
}
|
||||
|
||||
if( eErr != CE_None )
|
||||
continue;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Determine what polygon the various pixels belong to (redoing */
|
||||
/* the same thing done in the first pass above). */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( iY == nYSize )
|
||||
{
|
||||
for( iX = 0; iX < nXSize+2; iX++ )
|
||||
panThisLineId[iX] = -1;
|
||||
}
|
||||
else if( iY == 0 )
|
||||
oSecondEnum.ProcessLine(
|
||||
NULL, pafThisLineVal, NULL, panThisLineId+1, nXSize );
|
||||
else
|
||||
oSecondEnum.ProcessLine(
|
||||
pafLastLineVal, pafThisLineVal,
|
||||
panLastLineId+1, panThisLineId+1,
|
||||
nXSize );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Add polygon edges to our polygon list for the pixel */
|
||||
/* boundaries within and above this line. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( iX = 0; iX < nXSize+1; iX++ )
|
||||
{
|
||||
AddEdges( panThisLineId, panLastLineId,
|
||||
oFirstEnum.panPolyIdMap, oFirstEnum.pafPolyValue,
|
||||
papoPoly, iX, iY );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Periodically we scan out polygons and write out those that */
|
||||
/* haven't been added to on the last line as we can be sure */
|
||||
/* they are complete. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( iY % 8 == 7 )
|
||||
{
|
||||
for( iX = 0;
|
||||
eErr == CE_None && iX < oSecondEnum.nNextPolygonId;
|
||||
iX++ )
|
||||
{
|
||||
if( papoPoly[iX] && papoPoly[iX]->nLastLineUpdated < iY-1 )
|
||||
{
|
||||
if( hMaskBand == NULL
|
||||
|| !GDALFloatEquals(papoPoly[iX]->fPolyValue, GP_NODATA_MARKER) )
|
||||
{
|
||||
eErr =
|
||||
EmitPolygonToLayer( hOutLayer, iPixValField,
|
||||
papoPoly[iX], adfGeoTransform );
|
||||
}
|
||||
delete papoPoly[iX];
|
||||
papoPoly[iX] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Swap pixel value, and polygon id lines to be ready for the */
|
||||
/* next line. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
float *pafTmp = pafLastLineVal;
|
||||
pafLastLineVal = pafThisLineVal;
|
||||
pafThisLineVal = pafTmp;
|
||||
|
||||
GInt32 *panTmp = panThisLineId;
|
||||
panThisLineId = panLastLineId;
|
||||
panLastLineId = panTmp;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Report progress, and support interrupts. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( eErr == CE_None
|
||||
&& !pfnProgress( 0.10 + 0.90 * ((iY+1) / (double) nYSize),
|
||||
"", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
eErr = CE_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Make a cleanup pass for all unflushed polygons. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( iX = 0; eErr == CE_None && iX < oSecondEnum.nNextPolygonId; iX++ )
|
||||
{
|
||||
if( papoPoly[iX] )
|
||||
{
|
||||
if( hMaskBand == NULL
|
||||
|| !GDALFloatEquals(papoPoly[iX]->fPolyValue, GP_NODATA_MARKER) )
|
||||
{
|
||||
eErr =
|
||||
EmitPolygonToLayer( hOutLayer, iPixValField,
|
||||
papoPoly[iX], adfGeoTransform );
|
||||
}
|
||||
delete papoPoly[iX];
|
||||
papoPoly[iX] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Cleanup */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLFree( panThisLineId );
|
||||
CPLFree( panLastLineId );
|
||||
CPLFree( pafThisLineVal );
|
||||
CPLFree( pafLastLineVal );
|
||||
CPLFree( pabyMaskLine );
|
||||
CPLFree( papoPoly );
|
||||
|
||||
return eErr;
|
||||
#endif // OGR_ENABLED
|
||||
}
|
||||
|
||||
482
bazaar/plugin/gdal/alg/gdal_alg.h
Normal file
482
bazaar/plugin/gdal/alg/gdal_alg.h
Normal file
|
|
@ -0,0 +1,482 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdal_alg.h 27850 2014-10-12 16:58:09Z rouault $
|
||||
*
|
||||
* Project: GDAL Image Processing Algorithms
|
||||
* Purpose: Prototypes, and definitions for various GDAL based algorithms.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2001, Frank Warmerdam
|
||||
* Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef GDAL_ALG_H_INCLUDED
|
||||
#define GDAL_ALG_H_INCLUDED
|
||||
|
||||
/**
|
||||
* \file gdal_alg.h
|
||||
*
|
||||
* Public (C callable) GDAL algorithm entry points, and definitions.
|
||||
*/
|
||||
|
||||
#ifndef DOXYGEN_SKIP
|
||||
#include "gdal.h"
|
||||
#include "cpl_minixml.h"
|
||||
#include "ogr_api.h"
|
||||
#endif
|
||||
|
||||
CPL_C_START
|
||||
|
||||
int CPL_DLL CPL_STDCALL GDALComputeMedianCutPCT( GDALRasterBandH hRed,
|
||||
GDALRasterBandH hGreen,
|
||||
GDALRasterBandH hBlue,
|
||||
int (*pfnIncludePixel)(int,int,void*),
|
||||
int nColors,
|
||||
GDALColorTableH hColorTable,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg );
|
||||
|
||||
int CPL_DLL CPL_STDCALL GDALDitherRGB2PCT( GDALRasterBandH hRed,
|
||||
GDALRasterBandH hGreen,
|
||||
GDALRasterBandH hBlue,
|
||||
GDALRasterBandH hTarget,
|
||||
GDALColorTableH hColorTable,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg );
|
||||
|
||||
int CPL_DLL CPL_STDCALL GDALChecksumImage( GDALRasterBandH hBand,
|
||||
int nXOff, int nYOff, int nXSize, int nYSize );
|
||||
|
||||
CPLErr CPL_DLL CPL_STDCALL
|
||||
GDALComputeProximity( GDALRasterBandH hSrcBand,
|
||||
GDALRasterBandH hProximityBand,
|
||||
char **papszOptions,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg );
|
||||
|
||||
CPLErr CPL_DLL CPL_STDCALL
|
||||
GDALFillNodata( GDALRasterBandH hTargetBand,
|
||||
GDALRasterBandH hMaskBand,
|
||||
double dfMaxSearchDist,
|
||||
int bDeprecatedOption,
|
||||
int nSmoothingIterations,
|
||||
char **papszOptions,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg );
|
||||
|
||||
CPLErr CPL_DLL CPL_STDCALL
|
||||
GDALPolygonize( GDALRasterBandH hSrcBand,
|
||||
GDALRasterBandH hMaskBand,
|
||||
OGRLayerH hOutLayer, int iPixValField,
|
||||
char **papszOptions,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg );
|
||||
|
||||
CPLErr CPL_DLL CPL_STDCALL
|
||||
GDALFPolygonize( GDALRasterBandH hSrcBand,
|
||||
GDALRasterBandH hMaskBand,
|
||||
OGRLayerH hOutLayer, int iPixValField,
|
||||
char **papszOptions,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg );
|
||||
|
||||
CPLErr CPL_DLL CPL_STDCALL
|
||||
GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
|
||||
GDALRasterBandH hDstBand,
|
||||
int nSizeThreshold, int nConnectedness,
|
||||
char **papszOptions,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg );
|
||||
|
||||
/*
|
||||
* Warp Related.
|
||||
*/
|
||||
|
||||
typedef int
|
||||
(*GDALTransformerFunc)( void *pTransformerArg,
|
||||
int bDstToSrc, int nPointCount,
|
||||
double *x, double *y, double *z, int *panSuccess );
|
||||
|
||||
#define GDAL_GTI2_SIGNATURE "GTI2"
|
||||
|
||||
typedef struct {
|
||||
GByte abySignature[4];
|
||||
const char *pszClassName;
|
||||
GDALTransformerFunc pfnTransform;
|
||||
void (*pfnCleanup)( void * pTransformerArg );
|
||||
CPLXMLNode *(*pfnSerialize)( void * pTransformerArg );
|
||||
void* (*pfnCreateSimilar)( void* pTransformerArg, double dfSrcRatioX, double dfSrcRatioY );
|
||||
} GDALTransformerInfo;
|
||||
|
||||
void CPL_DLL GDALDestroyTransformer( void *pTransformerArg );
|
||||
int CPL_DLL GDALUseTransformer( void *pTranformerArg,
|
||||
int bDstToSrc, int nPointCount,
|
||||
double *x, double *y, double *z,
|
||||
int *panSuccess );
|
||||
void* GDALCreateSimilarTransformer( void* psTransformerArg, double dfSrcRatioX, double dfSrcRatioY );
|
||||
|
||||
|
||||
/* High level transformer for going from image coordinates on one file
|
||||
to image coordiantes on another, potentially doing reprojection,
|
||||
utilizing GCPs or using the geotransform. */
|
||||
|
||||
void CPL_DLL *
|
||||
GDALCreateGenImgProjTransformer( GDALDatasetH hSrcDS, const char *pszSrcWKT,
|
||||
GDALDatasetH hDstDS, const char *pszDstWKT,
|
||||
int bGCPUseOK, double dfGCPErrorThreshold,
|
||||
int nOrder );
|
||||
void CPL_DLL *
|
||||
GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
|
||||
char **papszOptions );
|
||||
void CPL_DLL *
|
||||
GDALCreateGenImgProjTransformer3( const char *pszSrcWKT,
|
||||
const double *padfSrcGeoTransform,
|
||||
const char *pszDstWKT,
|
||||
const double *padfDstGeoTransform );
|
||||
void CPL_DLL GDALSetGenImgProjTransformerDstGeoTransform( void *,
|
||||
const double * );
|
||||
void CPL_DLL GDALDestroyGenImgProjTransformer( void * );
|
||||
int CPL_DLL GDALGenImgProjTransform(
|
||||
void *pTransformArg, int bDstToSrc, int nPointCount,
|
||||
double *x, double *y, double *z, int *panSuccess );
|
||||
|
||||
void GDALSetTransformerDstGeoTransform( void *, const double * );
|
||||
|
||||
/* Geo to geo reprojection transformer. */
|
||||
void CPL_DLL *
|
||||
GDALCreateReprojectionTransformer( const char *pszSrcWKT,
|
||||
const char *pszDstWKT );
|
||||
void CPL_DLL GDALDestroyReprojectionTransformer( void * );
|
||||
int CPL_DLL GDALReprojectionTransform(
|
||||
void *pTransformArg, int bDstToSrc, int nPointCount,
|
||||
double *x, double *y, double *z, int *panSuccess );
|
||||
|
||||
/* GCP based transformer ... forward is to georef coordinates */
|
||||
void CPL_DLL *
|
||||
GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
|
||||
int nReqOrder, int bReversed );
|
||||
|
||||
/* GCP based transformer with refinement of the GCPs ... forward is to georef coordinates */
|
||||
void CPL_DLL *
|
||||
GDALCreateGCPRefineTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
|
||||
int nReqOrder, int bReversed, double tolerance, int minimumGcps);
|
||||
|
||||
void CPL_DLL GDALDestroyGCPTransformer( void *pTransformArg );
|
||||
int CPL_DLL GDALGCPTransform(
|
||||
void *pTransformArg, int bDstToSrc, int nPointCount,
|
||||
double *x, double *y, double *z, int *panSuccess );
|
||||
|
||||
/* Thin Plate Spine transformer ... forward is to georef coordinates */
|
||||
|
||||
void CPL_DLL *
|
||||
GDALCreateTPSTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
|
||||
int bReversed );
|
||||
void CPL_DLL GDALDestroyTPSTransformer( void *pTransformArg );
|
||||
int CPL_DLL GDALTPSTransform(
|
||||
void *pTransformArg, int bDstToSrc, int nPointCount,
|
||||
double *x, double *y, double *z, int *panSuccess );
|
||||
|
||||
char CPL_DLL ** RPCInfoToMD( GDALRPCInfo *psRPCInfo );
|
||||
|
||||
/* RPC based transformer ... src is pixel/line/elev, dst is long/lat/elev */
|
||||
|
||||
void CPL_DLL *
|
||||
GDALCreateRPCTransformer( GDALRPCInfo *psRPC, int bReversed,
|
||||
double dfPixErrThreshold,
|
||||
char **papszOptions );
|
||||
void CPL_DLL GDALDestroyRPCTransformer( void *pTransformArg );
|
||||
int CPL_DLL GDALRPCTransform(
|
||||
void *pTransformArg, int bDstToSrc, int nPointCount,
|
||||
double *x, double *y, double *z, int *panSuccess );
|
||||
|
||||
/* Geolocation transformer */
|
||||
|
||||
void CPL_DLL *
|
||||
GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
|
||||
char **papszGeolocationInfo,
|
||||
int bReversed );
|
||||
void CPL_DLL GDALDestroyGeoLocTransformer( void *pTransformArg );
|
||||
int CPL_DLL GDALGeoLocTransform(
|
||||
void *pTransformArg, int bDstToSrc, int nPointCount,
|
||||
double *x, double *y, double *z, int *panSuccess );
|
||||
|
||||
/* Approximate transformer */
|
||||
void CPL_DLL *
|
||||
GDALCreateApproxTransformer( GDALTransformerFunc pfnRawTransformer,
|
||||
void *pRawTransformerArg, double dfMaxError );
|
||||
void CPL_DLL GDALApproxTransformerOwnsSubtransformer( void *pCBData,
|
||||
int bOwnFlag );
|
||||
void CPL_DLL GDALDestroyApproxTransformer( void *pApproxArg );
|
||||
int CPL_DLL GDALApproxTransform(
|
||||
void *pTransformArg, int bDstToSrc, int nPointCount,
|
||||
double *x, double *y, double *z, int *panSuccess );
|
||||
|
||||
|
||||
|
||||
|
||||
int CPL_DLL CPL_STDCALL
|
||||
GDALSimpleImageWarp( GDALDatasetH hSrcDS,
|
||||
GDALDatasetH hDstDS,
|
||||
int nBandCount, int *panBandList,
|
||||
GDALTransformerFunc pfnTransform,
|
||||
void *pTransformArg,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void *pProgressArg,
|
||||
char **papszWarpOptions );
|
||||
|
||||
CPLErr CPL_DLL CPL_STDCALL
|
||||
GDALSuggestedWarpOutput( GDALDatasetH hSrcDS,
|
||||
GDALTransformerFunc pfnTransformer,
|
||||
void *pTransformArg,
|
||||
double *padfGeoTransformOut,
|
||||
int *pnPixels, int *pnLines );
|
||||
CPLErr CPL_DLL CPL_STDCALL
|
||||
GDALSuggestedWarpOutput2( GDALDatasetH hSrcDS,
|
||||
GDALTransformerFunc pfnTransformer,
|
||||
void *pTransformArg,
|
||||
double *padfGeoTransformOut,
|
||||
int *pnPixels, int *pnLines,
|
||||
double *padfExtents,
|
||||
int nOptions );
|
||||
|
||||
CPLXMLNode CPL_DLL *
|
||||
GDALSerializeTransformer( GDALTransformerFunc pfnFunc, void *pTransformArg );
|
||||
CPLErr CPL_DLL GDALDeserializeTransformer( CPLXMLNode *psTree,
|
||||
GDALTransformerFunc *ppfnFunc,
|
||||
void **ppTransformArg );
|
||||
|
||||
CPLErr CPL_DLL
|
||||
GDALTransformGeolocations( GDALRasterBandH hXBand,
|
||||
GDALRasterBandH hYBand,
|
||||
GDALRasterBandH hZBand,
|
||||
GDALTransformerFunc pfnTransformer,
|
||||
void *pTransformArg,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void *pProgressArg,
|
||||
char **papszOptions );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Contour Line Generation */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
typedef CPLErr (*GDALContourWriter)( double dfLevel, int nPoints,
|
||||
double *padfX, double *padfY, void * );
|
||||
|
||||
typedef void *GDALContourGeneratorH;
|
||||
|
||||
GDALContourGeneratorH CPL_DLL
|
||||
GDAL_CG_Create( int nWidth, int nHeight,
|
||||
int bNoDataSet, double dfNoDataValue,
|
||||
double dfContourInterval, double dfContourBase,
|
||||
GDALContourWriter pfnWriter, void *pCBData );
|
||||
CPLErr CPL_DLL GDAL_CG_FeedLine( GDALContourGeneratorH hCG,
|
||||
double *padfScanline );
|
||||
void CPL_DLL GDAL_CG_Destroy( GDALContourGeneratorH hCG );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *hLayer;
|
||||
|
||||
double adfGeoTransform[6];
|
||||
|
||||
int nElevField;
|
||||
int nIDField;
|
||||
int nNextID;
|
||||
} OGRContourWriterInfo;
|
||||
|
||||
CPLErr CPL_DLL
|
||||
OGRContourWriter( double, int, double *, double *, void *pInfo );
|
||||
|
||||
CPLErr CPL_DLL
|
||||
GDALContourGenerate( GDALRasterBandH hBand,
|
||||
double dfContourInterval, double dfContourBase,
|
||||
int nFixedLevelCount, double *padfFixedLevels,
|
||||
int bUseNoData, double dfNoDataValue,
|
||||
void *hLayer, int iIDField, int iElevField,
|
||||
GDALProgressFunc pfnProgress, void *pProgressArg );
|
||||
|
||||
/************************************************************************/
|
||||
/* Rasterizer API - geometries burned into GDAL raster. */
|
||||
/************************************************************************/
|
||||
|
||||
CPLErr CPL_DLL
|
||||
GDALRasterizeGeometries( GDALDatasetH hDS,
|
||||
int nBandCount, int *panBandList,
|
||||
int nGeomCount, OGRGeometryH *pahGeometries,
|
||||
GDALTransformerFunc pfnTransformer,
|
||||
void *pTransformArg,
|
||||
double *padfGeomBurnValue,
|
||||
char **papszOptions,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg );
|
||||
CPLErr CPL_DLL
|
||||
GDALRasterizeLayers( GDALDatasetH hDS,
|
||||
int nBandCount, int *panBandList,
|
||||
int nLayerCount, OGRLayerH *pahLayers,
|
||||
GDALTransformerFunc pfnTransformer,
|
||||
void *pTransformArg,
|
||||
double *padfLayerBurnValues,
|
||||
char **papszOptions,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void *pProgressArg );
|
||||
|
||||
CPLErr CPL_DLL
|
||||
GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
|
||||
GDALDataType eBufType, int nPixelSpace, int nLineSpace,
|
||||
int nLayerCount, OGRLayerH *pahLayers,
|
||||
const char *pszDstProjection,
|
||||
double *padfDstGeoTransform,
|
||||
GDALTransformerFunc pfnTransformer,
|
||||
void *pTransformArg, double dfBurnValue,
|
||||
char **papszOptions, GDALProgressFunc pfnProgress,
|
||||
void *pProgressArg );
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Gridding interface. */
|
||||
/************************************************************************/
|
||||
|
||||
/** Gridding Algorithms */
|
||||
typedef enum {
|
||||
/*! Inverse distance to a power */ GGA_InverseDistanceToAPower = 1,
|
||||
/*! Moving Average */ GGA_MovingAverage = 2,
|
||||
/*! Nearest Neighbor */ GGA_NearestNeighbor = 3,
|
||||
/*! Minimum Value (Data Metric) */ GGA_MetricMinimum = 4,
|
||||
/*! Maximum Value (Data Metric) */ GGA_MetricMaximum = 5,
|
||||
/*! Data Range (Data Metric) */ GGA_MetricRange = 6,
|
||||
/*! Number of Points (Data Metric) */ GGA_MetricCount = 7,
|
||||
/*! Average Distance (Data Metric) */ GGA_MetricAverageDistance = 8,
|
||||
/*! Average Distance Between Data Points (Data Metric) */
|
||||
GGA_MetricAverageDistancePts = 9
|
||||
} GDALGridAlgorithm;
|
||||
|
||||
/** Inverse distance to a power method control options */
|
||||
typedef struct
|
||||
{
|
||||
/*! Weighting power. */
|
||||
double dfPower;
|
||||
/*! Smoothing parameter. */
|
||||
double dfSmoothing;
|
||||
/*! Reserved for future use. */
|
||||
double dfAnisotropyRatio;
|
||||
/*! Reserved for future use. */
|
||||
double dfAnisotropyAngle;
|
||||
/*! The first radius (X axis if rotation angle is 0) of search ellipse. */
|
||||
double dfRadius1;
|
||||
/*! The second radius (Y axis if rotation angle is 0) of search ellipse. */
|
||||
double dfRadius2;
|
||||
/*! Angle of ellipse rotation in degrees.
|
||||
*
|
||||
* Ellipse rotated counter clockwise.
|
||||
*/
|
||||
double dfAngle;
|
||||
/*! Maximum number of data points to use.
|
||||
*
|
||||
* Do not search for more points than this number.
|
||||
* If less amount of points found the grid node considered empty and will
|
||||
* be filled with NODATA marker.
|
||||
*/
|
||||
GUInt32 nMaxPoints;
|
||||
/*! Minimum number of data points to use.
|
||||
*
|
||||
* If less amount of points found the grid node considered empty and will
|
||||
* be filled with NODATA marker.
|
||||
*/
|
||||
GUInt32 nMinPoints;
|
||||
/*! No data marker to fill empty points. */
|
||||
double dfNoDataValue;
|
||||
} GDALGridInverseDistanceToAPowerOptions;
|
||||
|
||||
/** Moving average method control options */
|
||||
typedef struct
|
||||
{
|
||||
/*! The first radius (X axis if rotation angle is 0) of search ellipse. */
|
||||
double dfRadius1;
|
||||
/*! The second radius (Y axis if rotation angle is 0) of search ellipse. */
|
||||
double dfRadius2;
|
||||
/*! Angle of ellipse rotation in degrees.
|
||||
*
|
||||
* Ellipse rotated counter clockwise.
|
||||
*/
|
||||
double dfAngle;
|
||||
/*! Minimum number of data points to average.
|
||||
*
|
||||
* If less amount of points found the grid node considered empty and will
|
||||
* be filled with NODATA marker.
|
||||
*/
|
||||
GUInt32 nMinPoints;
|
||||
/*! No data marker to fill empty points. */
|
||||
double dfNoDataValue;
|
||||
} GDALGridMovingAverageOptions;
|
||||
|
||||
/** Nearest neighbor method control options */
|
||||
typedef struct
|
||||
{
|
||||
/*! The first radius (X axis if rotation angle is 0) of search ellipse. */
|
||||
double dfRadius1;
|
||||
/*! The second radius (Y axis if rotation angle is 0) of search ellipse. */
|
||||
double dfRadius2;
|
||||
/*! Angle of ellipse rotation in degrees.
|
||||
*
|
||||
* Ellipse rotated counter clockwise.
|
||||
*/
|
||||
double dfAngle;
|
||||
/*! No data marker to fill empty points. */
|
||||
double dfNoDataValue;
|
||||
} GDALGridNearestNeighborOptions;
|
||||
|
||||
/** Data metrics method control options */
|
||||
typedef struct
|
||||
{
|
||||
/*! The first radius (X axis if rotation angle is 0) of search ellipse. */
|
||||
double dfRadius1;
|
||||
/*! The second radius (Y axis if rotation angle is 0) of search ellipse. */
|
||||
double dfRadius2;
|
||||
/*! Angle of ellipse rotation in degrees.
|
||||
*
|
||||
* Ellipse rotated counter clockwise.
|
||||
*/
|
||||
double dfAngle;
|
||||
/*! Minimum number of data points to average.
|
||||
*
|
||||
* If less amount of points found the grid node considered empty and will
|
||||
* be filled with NODATA marker.
|
||||
*/
|
||||
GUInt32 nMinPoints;
|
||||
/*! No data marker to fill empty points. */
|
||||
double dfNoDataValue;
|
||||
} GDALGridDataMetricsOptions;
|
||||
|
||||
CPLErr CPL_DLL
|
||||
GDALGridCreate( GDALGridAlgorithm, const void *, GUInt32,
|
||||
const double *, const double *, const double *,
|
||||
double, double, double, double,
|
||||
GUInt32, GUInt32, GDALDataType, void *,
|
||||
GDALProgressFunc, void *);
|
||||
|
||||
GDAL_GCP CPL_DLL *
|
||||
GDALComputeMatchingPoints( GDALDatasetH hFirstImage,
|
||||
GDALDatasetH hSecondImage,
|
||||
char **papszOptions,
|
||||
int *pnGCPCount );
|
||||
CPL_C_END
|
||||
|
||||
#endif /* ndef GDAL_ALG_H_INCLUDED */
|
||||
229
bazaar/plugin/gdal/alg/gdal_alg_priv.h
Normal file
229
bazaar/plugin/gdal/alg/gdal_alg_priv.h
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdal_alg_priv.h 28826 2015-03-30 17:51:14Z rouault $
|
||||
*
|
||||
* Project: GDAL Image Processing Algorithms
|
||||
* Purpose: Prototypes and definitions for various GDAL based algorithms:
|
||||
* private declarations.
|
||||
* Author: Andrey Kiselev, dron@ak4719.spb.edu
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2008, Andrey Kiselev <dron@ak4719.spb.edu>
|
||||
* Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef GDAL_ALG_PRIV_H_INCLUDED
|
||||
#define GDAL_ALG_PRIV_H_INCLUDED
|
||||
|
||||
#include "gdal_alg.h"
|
||||
|
||||
CPL_C_START
|
||||
|
||||
/** Source of the burn value */
|
||||
typedef enum {
|
||||
/*! Use value from padfBurnValue */ GBV_UserBurnValue = 0,
|
||||
/*! Use value from the Z coordinate */ GBV_Z = 1,
|
||||
/*! Use value form the M value */ GBV_M = 2
|
||||
} GDALBurnValueSrc;
|
||||
|
||||
typedef enum {
|
||||
GRMA_Replace = 0,
|
||||
GRMA_Add = 1,
|
||||
} GDALRasterMergeAlg;
|
||||
|
||||
typedef struct {
|
||||
unsigned char * pabyChunkBuf;
|
||||
int nXSize;
|
||||
int nYSize;
|
||||
int nBands;
|
||||
GDALDataType eType;
|
||||
double *padfBurnValue;
|
||||
GDALBurnValueSrc eBurnValueSource;
|
||||
GDALRasterMergeAlg eMergeAlg;
|
||||
} GDALRasterizeInfo;
|
||||
|
||||
/************************************************************************/
|
||||
/* Low level rasterizer API. */
|
||||
/************************************************************************/
|
||||
|
||||
typedef void (*llScanlineFunc)( void *, int, int, int, double );
|
||||
typedef void (*llPointFunc)( void *, int, int, double );
|
||||
|
||||
void GDALdllImagePoint( int nRasterXSize, int nRasterYSize,
|
||||
int nPartCount, int *panPartSize,
|
||||
double *padfX, double *padfY, double *padfVariant,
|
||||
llPointFunc pfnPointFunc, void *pCBData );
|
||||
|
||||
void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
|
||||
int nPartCount, int *panPartSize,
|
||||
double *padfX, double *padfY, double *padfVariant,
|
||||
llPointFunc pfnPointFunc, void *pCBData );
|
||||
|
||||
void GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
|
||||
int nPartCount, int *panPartSize,
|
||||
double *padfX, double *padfY,
|
||||
double *padfVariant,
|
||||
llPointFunc pfnPointFunc, void *pCBData );
|
||||
|
||||
void GDALdllImageFilledPolygon(int nRasterXSize, int nRasterYSize,
|
||||
int nPartCount, int *panPartSize,
|
||||
double *padfX, double *padfY,
|
||||
double *padfVariant,
|
||||
llScanlineFunc pfnScanlineFunc, void *pCBData );
|
||||
|
||||
CPL_C_END
|
||||
|
||||
/************************************************************************/
|
||||
/* Polygon Enumerator */
|
||||
/************************************************************************/
|
||||
|
||||
#define GP_NODATA_MARKER -51502112
|
||||
|
||||
class GDALRasterPolygonEnumerator
|
||||
|
||||
{
|
||||
private:
|
||||
void MergePolygon( int nSrcId, int nDstId );
|
||||
int NewPolygon( GInt32 nValue );
|
||||
|
||||
public: // these are intended to be readonly.
|
||||
|
||||
GInt32 *panPolyIdMap;
|
||||
GInt32 *panPolyValue;
|
||||
|
||||
int nNextPolygonId;
|
||||
int nPolyAlloc;
|
||||
|
||||
int nConnectedness;
|
||||
|
||||
public:
|
||||
GDALRasterPolygonEnumerator( int nConnectedness=4 );
|
||||
~GDALRasterPolygonEnumerator();
|
||||
|
||||
void ProcessLine( GInt32 *panLastLineVal, GInt32 *panThisLineVal,
|
||||
GInt32 *panLastLineId, GInt32 *panThisLineId,
|
||||
int nXSize );
|
||||
|
||||
void CompleteMerges();
|
||||
|
||||
void Clear();
|
||||
};
|
||||
|
||||
#ifdef OGR_ENABLED
|
||||
/************************************************************************/
|
||||
/* Polygon Enumerator */
|
||||
/* */
|
||||
/* Buffers has float values instead og GInt32 */
|
||||
/************************************************************************/
|
||||
class GDALRasterFPolygonEnumerator
|
||||
|
||||
{
|
||||
private:
|
||||
void MergePolygon( int nSrcId, int nDstId );
|
||||
int NewPolygon( float fValue );
|
||||
|
||||
public: // these are intended to be readonly.
|
||||
|
||||
GInt32 *panPolyIdMap;
|
||||
float *pafPolyValue;
|
||||
|
||||
int nNextPolygonId;
|
||||
int nPolyAlloc;
|
||||
|
||||
int nConnectedness;
|
||||
|
||||
public:
|
||||
GDALRasterFPolygonEnumerator( int nConnectedness=4 );
|
||||
~GDALRasterFPolygonEnumerator();
|
||||
|
||||
void ProcessLine( float *pafLastLineVal, float *pafThisLineVal,
|
||||
GInt32 *panLastLineId, GInt32 *panThisLineId,
|
||||
int nXSize );
|
||||
|
||||
void CompleteMerges();
|
||||
|
||||
void Clear();
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef void* (*GDALTransformDeserializeFunc)( CPLXMLNode *psTree );
|
||||
|
||||
void* GDALRegisterTransformDeserializer(const char* pszTransformName,
|
||||
GDALTransformerFunc pfnTransformerFunc,
|
||||
GDALTransformDeserializeFunc pfnDeserializeFunc);
|
||||
void GDALUnregisterTransformDeserializer(void* pData);
|
||||
|
||||
void GDALCleanupTransformDeserializerMutex();
|
||||
|
||||
/* Transformer cloning */
|
||||
|
||||
void* GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList,
|
||||
int bReversed, char** papszOptions );
|
||||
|
||||
void CPL_DLL * GDALCloneTransformer( void *pTranformerArg );
|
||||
|
||||
/************************************************************************/
|
||||
/* Color table related */
|
||||
/************************************************************************/
|
||||
|
||||
int
|
||||
GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
|
||||
GDALRasterBandH hGreen,
|
||||
GDALRasterBandH hBlue,
|
||||
GByte* pabyRedBand,
|
||||
GByte* pabyGreenBand,
|
||||
GByte* pabyBlueBand,
|
||||
int (*pfnIncludePixel)(int,int,void*),
|
||||
int nColors,
|
||||
int nBits,
|
||||
int* panHistogram,
|
||||
GDALColorTableH hColorTable,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg );
|
||||
|
||||
int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
|
||||
GDALRasterBandH hGreen,
|
||||
GDALRasterBandH hBlue,
|
||||
GDALRasterBandH hTarget,
|
||||
GDALColorTableH hColorTable,
|
||||
int nBits,
|
||||
GInt16* pasDynamicColorMap,
|
||||
int bDither,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg );
|
||||
|
||||
#define PRIME_FOR_65536 98317
|
||||
#define MEDIAN_CUT_AND_DITHER_BUFFER_SIZE_65536 (6 * sizeof(int) * PRIME_FOR_65536)
|
||||
|
||||
/************************************************************************/
|
||||
/* Float comparison function. */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Units in the Last Place. This specifies how big an error we are willing to
|
||||
* accept in terms of the value of the least significant digit of the floating
|
||||
* point number’s representation. MAX_ULPS can also be interpreted in terms of
|
||||
* how many representable floats we are willing to accept between A and B.
|
||||
*/
|
||||
#define MAX_ULPS 10
|
||||
|
||||
GBool GDALFloatEquals(float A, float B);
|
||||
|
||||
#endif /* ndef GDAL_ALG_PRIV_H_INCLUDED */
|
||||
1166
bazaar/plugin/gdal/alg/gdal_crs.c
Normal file
1166
bazaar/plugin/gdal/alg/gdal_crs.c
Normal file
File diff suppressed because it is too large
Load diff
287
bazaar/plugin/gdal/alg/gdal_nrgcrs.c
Normal file
287
bazaar/plugin/gdal/alg/gdal_nrgcrs.c
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdal_nrgcrs.c 23156 2011-10-01 15:34:16Z rouault $
|
||||
*
|
||||
* Project: Mapinfo Image Warper
|
||||
* Purpose: Implemention of the GDALTransformer wrapper around CRS.C functions
|
||||
* to build a polynomial transformation based on ground control
|
||||
* points.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
***************************************************************************
|
||||
* Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_alg.h"
|
||||
#include "cpl_conv.h"
|
||||
#include "cpl_minixml.h"
|
||||
|
||||
extern int TwoDPolyFit( double *, double *, int, int, double *, double *, double * );
|
||||
extern double TwoDPolyEval( double *, int, double, double );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double adfToGeoX[20];
|
||||
double adfToGeoY[20];
|
||||
|
||||
double adfFromGeoX[20];
|
||||
double adfFromGeoY[20];
|
||||
|
||||
int nOrder;
|
||||
int bReversed;
|
||||
|
||||
} GCPTransformInfo;
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALCreateGCPTransformer() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Create GCP based polynomial transformer.
|
||||
*
|
||||
* Computes least squares fit polynomials from a provided set of GCPs,
|
||||
* and stores the coefficients for later transformation of points between
|
||||
* pixel/line and georeferenced coordinates.
|
||||
*
|
||||
* The return value should be used as a TransformArg in combination with
|
||||
* the transformation function GDALGCPTransform which fits the
|
||||
* GDALTransformerFunc signature. The returned transform argument should
|
||||
* be deallocated with GDALDestroyGCPTransformer when no longer needed.
|
||||
*
|
||||
* This function may fail (returning NULL) if the provided set of GCPs
|
||||
* are inadequate for the requested order, the determinate is zero or they
|
||||
* are otherwise "ill conditioned".
|
||||
*
|
||||
* Note that 2nd order requires at least 6 GCPs, and 3rd order requires at
|
||||
* least 10 gcps. If nReqOrder is 0 the highest order possible with the
|
||||
* provided gcp count will be used.
|
||||
*
|
||||
* @param nGCPCount the number of GCPs in pasGCPList.
|
||||
* @param pasGCPList an array of GCPs to be used as input.
|
||||
* @param nReqOrder the requested polynomial order. It should be 1, 2 or 3.
|
||||
* @param bReversed set it to TRUE to compute the reversed transformation.
|
||||
*
|
||||
* @return the transform argument or NULL if creation fails.
|
||||
*/
|
||||
|
||||
void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
|
||||
int nReqOrder, int bReversed )
|
||||
|
||||
{
|
||||
GCPTransformInfo *psInfo;
|
||||
double *padfGeoX, *padfGeoY, *padfRasterX, *padfRasterY;
|
||||
int *panStatus, iGCP;
|
||||
double rms_err;
|
||||
|
||||
if( nReqOrder == 0 )
|
||||
{
|
||||
if( nGCPCount >= 10 )
|
||||
nReqOrder = 3;
|
||||
else if( nGCPCount >= 6 )
|
||||
nReqOrder = 2;
|
||||
else
|
||||
nReqOrder = 1;
|
||||
}
|
||||
|
||||
psInfo = (GCPTransformInfo *) CPLCalloc(sizeof(GCPTransformInfo),1);
|
||||
psInfo->bReversed = bReversed;
|
||||
psInfo->nOrder = nReqOrder;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Allocate and initialize the working points list. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
padfGeoX = (double *) CPLCalloc(sizeof(double),nGCPCount);
|
||||
padfGeoY = (double *) CPLCalloc(sizeof(double),nGCPCount);
|
||||
padfRasterX = (double *) CPLCalloc(sizeof(double),nGCPCount);
|
||||
padfRasterY = (double *) CPLCalloc(sizeof(double),nGCPCount);
|
||||
panStatus = (int *) CPLCalloc(sizeof(int),nGCPCount);
|
||||
|
||||
for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
|
||||
{
|
||||
panStatus[iGCP] = 1;
|
||||
padfGeoX[iGCP] = pasGCPList[iGCP].dfGCPX;
|
||||
padfGeoY[iGCP] = pasGCPList[iGCP].dfGCPY;
|
||||
padfRasterX[iGCP] = pasGCPList[iGCP].dfGCPPixel;
|
||||
padfRasterY[iGCP] = pasGCPList[iGCP].dfGCPLine;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Compute the forward and reverse polynomials. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if ( TwoDPolyFit( &rms_err, psInfo->adfFromGeoX, nReqOrder, nGCPCount,
|
||||
padfRasterX, padfGeoX, padfGeoY ) < 0 )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Failed to compute polynomial equations of desired order\n"
|
||||
"for provided control points." );
|
||||
goto CleanupAfterError;
|
||||
}
|
||||
if ( TwoDPolyFit( &rms_err, psInfo->adfFromGeoY, nReqOrder, nGCPCount,
|
||||
padfRasterY, padfGeoX, padfGeoY ) < 0 )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Failed to compute polynomial equations of desired order\n"
|
||||
"for provided control points." );
|
||||
goto CleanupAfterError;
|
||||
}
|
||||
if ( TwoDPolyFit( &rms_err, psInfo->adfToGeoX, nReqOrder, nGCPCount,
|
||||
padfGeoX, padfRasterX, padfRasterY ) < 0 )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Failed to compute polynomial equations of desired order\n"
|
||||
"for provided control points." );
|
||||
goto CleanupAfterError;
|
||||
}
|
||||
if ( TwoDPolyFit( &rms_err, psInfo->adfToGeoY, nReqOrder, nGCPCount,
|
||||
padfGeoY, padfRasterX, padfRasterY ) < 0 )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Failed to compute polynomial equations of desired order\n"
|
||||
"for provided control points." );
|
||||
goto CleanupAfterError;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Dump residuals. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLDebug( "GDALCreateGCPTransformer",
|
||||
"Number of GCPs %d, transformation order %d",
|
||||
nGCPCount, psInfo->nOrder );
|
||||
|
||||
for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
|
||||
{
|
||||
double x = pasGCPList[iGCP].dfGCPX;
|
||||
double y = pasGCPList[iGCP].dfGCPY;
|
||||
double z = pasGCPList[iGCP].dfGCPZ;
|
||||
int bSuccess;
|
||||
GDALGCPTransform( psInfo, TRUE, 1, &x, &y, &z, &bSuccess );
|
||||
CPLDebug( "GDALCreateGCPTransformer",
|
||||
"GCP %d. Residuals: X: %f, Y: %f", iGCP,
|
||||
pasGCPList[iGCP].dfGCPPixel - x, pasGCPList[iGCP].dfGCPLine - y );
|
||||
}
|
||||
|
||||
return psInfo;
|
||||
|
||||
CleanupAfterError:
|
||||
CPLFree( padfGeoX );
|
||||
CPLFree( padfGeoY );
|
||||
CPLFree( padfRasterX );
|
||||
CPLFree( padfRasterX );
|
||||
CPLFree( panStatus );
|
||||
|
||||
CPLFree( psInfo );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALDestroyGCPTransformer() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Destroy GCP transformer.
|
||||
*
|
||||
* This function is used to destroy information about a GCP based
|
||||
* polynomial transformation created with GDALCreateGCPTransformer().
|
||||
*
|
||||
* @param pTransformArg the transform arg previously returned by
|
||||
* GDALCreateGCPTransformer().
|
||||
*/
|
||||
|
||||
void GDALDestroyGCPTransformer( void *pTransformArg )
|
||||
|
||||
{
|
||||
CPLFree( pTransformArg );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALGCPTransform() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Transforms point based on GCP derived polynomial model.
|
||||
*
|
||||
* This function matches the GDALTransformerFunc signature, and can be
|
||||
* used to transform one or more points from pixel/line coordinates to
|
||||
* georeferenced coordinates (SrcToDst) or vice versa (DstToSrc).
|
||||
*
|
||||
* @param pTransformArg return value from GDALCreateGCPTransformer().
|
||||
* @param bDstToSrc TRUE if transformation is from the destination
|
||||
* (georeferenced) coordinates to pixel/line or FALSE when transforming
|
||||
* from pixel/line to georeferenced coordinates.
|
||||
* @param nPointCount the number of values in the x, y and z arrays.
|
||||
* @param x array containing the X values to be transformed.
|
||||
* @param y array containing the Y values to be transformed.
|
||||
* @param z array containing the Z values to be transformed.
|
||||
* @param panSuccess array in which a flag indicating success (TRUE) or
|
||||
* failure (FALSE) of the transformation are placed.
|
||||
*
|
||||
* @return TRUE.
|
||||
*/
|
||||
|
||||
int GDALGCPTransform( void *pTransformArg, int bDstToSrc,
|
||||
int nPointCount,
|
||||
double *x, double *y, double *z,
|
||||
int *panSuccess )
|
||||
|
||||
{
|
||||
int i;
|
||||
double X, Y;
|
||||
GCPTransformInfo *psInfo = (GCPTransformInfo *) pTransformArg;
|
||||
|
||||
if( psInfo->bReversed )
|
||||
bDstToSrc = !bDstToSrc;
|
||||
|
||||
for( i = 0; i < nPointCount; i++ )
|
||||
{
|
||||
X = x[i];
|
||||
Y = y[i];
|
||||
if( bDstToSrc )
|
||||
{
|
||||
x[i] = TwoDPolyEval( psInfo->adfFromGeoX, psInfo->nOrder, X, Y );
|
||||
y[i] = TwoDPolyEval( psInfo->adfFromGeoY, psInfo->nOrder, X, Y );
|
||||
}
|
||||
else
|
||||
{
|
||||
x[i] = TwoDPolyEval( psInfo->adfToGeoX, psInfo->nOrder, X, Y );
|
||||
y[i] = TwoDPolyEval( psInfo->adfToGeoY, psInfo->nOrder, X, Y );
|
||||
}
|
||||
z[i] = 0;
|
||||
panSuccess[i] = TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CPLXMLNode *GDALSerializeGCPTransformer( void *pTransformArg )
|
||||
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"serialization not supported for this type of gcp transformer.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree )
|
||||
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"deserialization not supported for this type of gcp transformer.");
|
||||
return NULL;
|
||||
}
|
||||
301
bazaar/plugin/gdal/alg/gdal_octave.cpp
Normal file
301
bazaar/plugin/gdal/alg/gdal_octave.cpp
Normal file
|
|
@ -0,0 +1,301 @@
|
|||
/******************************************************************************
|
||||
* Project: GDAL
|
||||
* Purpose: Correlator
|
||||
* Author: Andrew Migal, migal.drew@gmail.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2012, Andrew Migal
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_simplesurf.h"
|
||||
|
||||
CPL_CVSID("$Id");
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* GDALIntegralImage */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
GDALIntegralImage::GDALIntegralImage()
|
||||
{
|
||||
pMatrix = 0;
|
||||
nHeight = 0;
|
||||
nWidth = 0;
|
||||
}
|
||||
|
||||
int GDALIntegralImage::GetHeight() { return nHeight; }
|
||||
|
||||
int GDALIntegralImage::GetWidth() { return nWidth; }
|
||||
|
||||
void GDALIntegralImage::Initialize(const double **padfImg, int nHeight, int nWidth)
|
||||
{
|
||||
//Memory allocation
|
||||
pMatrix = new double*[nHeight];
|
||||
for (int i = 0; i < nHeight; i++)
|
||||
pMatrix[i] = new double[nWidth];
|
||||
|
||||
this->nHeight = nHeight;
|
||||
this->nWidth = nWidth;
|
||||
|
||||
//Integral image calculation
|
||||
for (int i = 0; i < nHeight; i++)
|
||||
for (int j = 0; j < nWidth; j++)
|
||||
{
|
||||
double val = padfImg[i][j];
|
||||
double a = 0, b = 0, c = 0;
|
||||
|
||||
if (i - 1 >= 0 && j - 1 >= 0)
|
||||
a = pMatrix[i - 1][j - 1];
|
||||
if (j - 1 >= 0)
|
||||
b = pMatrix[i][j - 1];
|
||||
if (i - 1 >= 0)
|
||||
c = pMatrix[i - 1][j];
|
||||
|
||||
//New value based on previous calculations
|
||||
pMatrix[i][j] = val - a + b + c;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns value of specified cell
|
||||
*/
|
||||
double GDALIntegralImage::GetValue(int nRow, int nCol)
|
||||
{
|
||||
if ((nRow >= 0 && nRow < nHeight) && (nCol >= 0 && nCol < nWidth))
|
||||
return pMatrix[nRow][nCol];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
double GDALIntegralImage::GetRectangleSum(int nRow, int nCol, int nWidth, int nHeight)
|
||||
{
|
||||
double a = 0, b = 0, c = 0, d = 0;
|
||||
|
||||
//Left top point of rectangle is first
|
||||
int w = nWidth - 1;
|
||||
int h = nHeight - 1;
|
||||
|
||||
int row = nRow;
|
||||
int col = nCol;
|
||||
|
||||
//Left top point
|
||||
int lt_row = (row <= this->nHeight) ? (row - 1) : -1;
|
||||
int lt_col = (col <= this->nWidth) ? (col - 1) : -1;
|
||||
//Right bottom point of the rectangle
|
||||
int rb_row = (row + h < this->nHeight) ? (row + h) : (this->nHeight - 1);
|
||||
int rb_col = (col + w < this->nWidth) ? (col + w) : (this->nWidth - 1);
|
||||
|
||||
if (lt_row >= 0 && lt_col >= 0)
|
||||
a = this->GetValue(lt_row, lt_col);
|
||||
|
||||
if (lt_row >= 0 && rb_col >= 0)
|
||||
b = this->GetValue(lt_row, rb_col);
|
||||
|
||||
if (rb_row >= 0 && rb_col >= 0)
|
||||
c = this->GetValue(rb_row, rb_col);
|
||||
|
||||
if (rb_row >= 0 && lt_col >= 0)
|
||||
d = this->GetValue(rb_row, lt_col);
|
||||
|
||||
double res = a + c - b - d;
|
||||
|
||||
return (res > 0) ? res : 0;
|
||||
}
|
||||
|
||||
double GDALIntegralImage::HaarWavelet_X(int nRow, int nCol, int nSize)
|
||||
{
|
||||
return GetRectangleSum(nRow, nCol + nSize / 2, nSize / 2, nSize)
|
||||
- GetRectangleSum(nRow, nCol, nSize / 2, nSize);
|
||||
}
|
||||
|
||||
double GDALIntegralImage::HaarWavelet_Y(int nRow, int nCol, int nSize)
|
||||
{
|
||||
return GetRectangleSum(nRow + nSize / 2, nCol, nSize, nSize / 2)
|
||||
- GetRectangleSum(nRow, nCol, nSize, nSize / 2);
|
||||
}
|
||||
|
||||
GDALIntegralImage::~GDALIntegralImage()
|
||||
{
|
||||
//Clean up memory
|
||||
for (int i = 0; i < nHeight; i++)
|
||||
delete[] pMatrix[i];
|
||||
|
||||
delete[] pMatrix;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* GDALOctaveLayer */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
GDALOctaveLayer::GDALOctaveLayer(int nOctave, int nInterval)
|
||||
{
|
||||
this->octaveNum = nOctave;
|
||||
this->filterSize = 3 * ((int)pow(2.0, nOctave) * nInterval + 1);
|
||||
this->radius = (this->filterSize - 1) / 2;
|
||||
this->scale = (int)pow(2.0, nOctave);
|
||||
this->width = 0;
|
||||
this->height = 0;
|
||||
|
||||
this->detHessians = 0;
|
||||
this->signs = 0;
|
||||
}
|
||||
|
||||
void GDALOctaveLayer::ComputeLayer(GDALIntegralImage *poImg)
|
||||
{
|
||||
this->width = poImg->GetWidth();
|
||||
this->height = poImg->GetHeight();
|
||||
|
||||
//Allocate memory for arrays
|
||||
this->detHessians = new double*[this->height];
|
||||
this->signs = new int*[this->height];
|
||||
|
||||
for (int i = 0; i < this->height; i++)
|
||||
{
|
||||
this->detHessians[i] = new double[this->width];
|
||||
this->signs[i] = new int[this->width];
|
||||
}
|
||||
//End Allocate memory for arrays
|
||||
|
||||
//Values of Fast Hessian filters
|
||||
double dxx, dyy, dxy;
|
||||
// 1/3 of filter side
|
||||
int lobe = filterSize / 3;
|
||||
|
||||
//Length of the longer side of the lobe in dxx and dyy filters
|
||||
int longPart = 2 * lobe - 1;
|
||||
|
||||
int normalization = filterSize * filterSize;
|
||||
|
||||
//Loop over image pixels
|
||||
//Filter should remain into image borders
|
||||
for (int r = radius; r <= height - radius; r++)
|
||||
for (int c = radius; c <= width - radius; c++)
|
||||
{
|
||||
dxx = poImg->GetRectangleSum(r - lobe + 1, c - radius, filterSize, longPart)
|
||||
- 3 * poImg->GetRectangleSum(r - lobe + 1, c - (lobe - 1) / 2, lobe, longPart);
|
||||
dyy = poImg->GetRectangleSum(r - radius, c - lobe - 1, longPart, filterSize)
|
||||
- 3 * poImg->GetRectangleSum(r - lobe + 1, c - lobe + 1, longPart, lobe);
|
||||
dxy = poImg->GetRectangleSum(r - lobe, c - lobe, lobe, lobe)
|
||||
+ poImg->GetRectangleSum(r + 1, c + 1, lobe, lobe)
|
||||
- poImg->GetRectangleSum(r - lobe, c + 1, lobe, lobe)
|
||||
- poImg->GetRectangleSum(r + 1, c - lobe, lobe, lobe);
|
||||
|
||||
dxx /= normalization;
|
||||
dyy /= normalization;
|
||||
dxy /= normalization;
|
||||
|
||||
//Memorize Hessian values and their signs
|
||||
detHessians[r][c] = dxx * dyy - 0.9 * 0.9 * dxy * dxy;
|
||||
signs[r][c] = (dxx + dyy >= 0) ? 1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
GDALOctaveLayer::~GDALOctaveLayer()
|
||||
{
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
delete[] detHessians[i];
|
||||
delete[] signs[i];
|
||||
}
|
||||
|
||||
delete[] detHessians;
|
||||
delete[] signs;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* GDALOctaveMap */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
GDALOctaveMap::GDALOctaveMap(int nOctaveStart, int nOctaveEnd)
|
||||
{
|
||||
this->octaveStart = nOctaveStart;
|
||||
this->octaveEnd = nOctaveEnd;
|
||||
|
||||
pMap = new GDALOctaveLayer**[octaveEnd];
|
||||
|
||||
for (int i = 0; i < nOctaveEnd; i++)
|
||||
pMap[i] = new GDALOctaveLayer*[INTERVALS];
|
||||
|
||||
for (int oct = octaveStart; oct <= octaveEnd; oct++)
|
||||
for (int i = 1; i <= INTERVALS; i++)
|
||||
pMap[oct - 1][i - 1] = new GDALOctaveLayer(oct, i);
|
||||
}
|
||||
|
||||
void GDALOctaveMap::ComputeMap(GDALIntegralImage *poImg)
|
||||
{
|
||||
for (int oct = octaveStart; oct <= octaveEnd; oct++)
|
||||
for (int i = 1; i <= INTERVALS; i++)
|
||||
pMap[oct - 1][i - 1]->ComputeLayer(poImg);
|
||||
}
|
||||
|
||||
bool GDALOctaveMap::PointIsExtremum(int row, int col, GDALOctaveLayer *bot,
|
||||
GDALOctaveLayer *mid, GDALOctaveLayer *top, double threshold)
|
||||
{
|
||||
//Check that point in middle layer has all neighbours
|
||||
if (row <= top->radius || col <= top->radius ||
|
||||
row + top->radius >= top->height || col + top->radius >= top->width)
|
||||
return false;
|
||||
|
||||
double curPoint = mid->detHessians[row][col];
|
||||
|
||||
//Hessian should be higher than threshold
|
||||
if (curPoint < threshold)
|
||||
return false;
|
||||
|
||||
//Hessian should be higher than hessians of all neighbours
|
||||
for (int i = -1; i <= 1; i++)
|
||||
for (int j = -1; j <= 1; j++)
|
||||
{
|
||||
double topPoint = top->detHessians[row + i][col + j];
|
||||
double midPoint = mid->detHessians[row + i][col + j];
|
||||
double botPoint = bot->detHessians[row + i][col + j];
|
||||
|
||||
if (topPoint >= curPoint || botPoint >= curPoint)
|
||||
return false;
|
||||
|
||||
if (i != 0 || j != 0)
|
||||
if (midPoint >= curPoint)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GDALOctaveMap::~GDALOctaveMap()
|
||||
{
|
||||
// Clean up Octave layers
|
||||
for (int oct = octaveStart; oct <= octaveEnd; oct++)
|
||||
for(int i = 0; i < INTERVALS; i++)
|
||||
delete pMap[oct - 1][i];
|
||||
|
||||
//Clean up allocated memory
|
||||
for (int oct = 0; oct < octaveEnd; oct++)
|
||||
delete[] pMap[oct];
|
||||
|
||||
delete[] pMap;
|
||||
}
|
||||
1430
bazaar/plugin/gdal/alg/gdal_rpc.cpp
Normal file
1430
bazaar/plugin/gdal/alg/gdal_rpc.cpp
Normal file
File diff suppressed because it is too large
Load diff
522
bazaar/plugin/gdal/alg/gdal_simplesurf.cpp
Normal file
522
bazaar/plugin/gdal/alg/gdal_simplesurf.cpp
Normal file
|
|
@ -0,0 +1,522 @@
|
|||
/******************************************************************************
|
||||
* Project: GDAL
|
||||
* Purpose: Correlator - GDALSimpleSURF and GDALFeaturePoint classes.
|
||||
* Author: Andrew Migal, migal.drew@gmail.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2012, Andrew Migal
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_simplesurf.h"
|
||||
|
||||
CPL_CVSID("$Id");
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* GDALFeaturePoint */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
GDALFeaturePoint::GDALFeaturePoint()
|
||||
{
|
||||
nX = -1;
|
||||
nY = -1;
|
||||
nScale = -1;
|
||||
nRadius = -1;
|
||||
nSign = -1;
|
||||
|
||||
padfDescriptor = new double[DESC_SIZE];
|
||||
}
|
||||
|
||||
GDALFeaturePoint::GDALFeaturePoint(const GDALFeaturePoint& fp)
|
||||
{
|
||||
nX = fp.nX;
|
||||
nY = fp.nY;
|
||||
nScale = fp.nScale;
|
||||
nRadius = fp.nRadius;
|
||||
nSign = fp.nSign;
|
||||
|
||||
padfDescriptor = new double[DESC_SIZE];
|
||||
for (int i = 0; i < DESC_SIZE; i++)
|
||||
padfDescriptor[i] = fp.padfDescriptor[i];
|
||||
}
|
||||
|
||||
GDALFeaturePoint::GDALFeaturePoint(int nX, int nY,
|
||||
int nScale, int nRadius, int nSign)
|
||||
{
|
||||
this->nX = nX;
|
||||
this->nY = nY;
|
||||
this->nScale = nScale;
|
||||
this->nRadius = nRadius;
|
||||
this->nSign = nSign;
|
||||
|
||||
this->padfDescriptor = new double[DESC_SIZE];
|
||||
}
|
||||
|
||||
GDALFeaturePoint& GDALFeaturePoint::operator=(const GDALFeaturePoint& point)
|
||||
{
|
||||
if (this != &point)
|
||||
{
|
||||
nX = point.nX;
|
||||
nY = point.nY;
|
||||
nScale = point.nScale;
|
||||
nRadius = point.nRadius;
|
||||
nSign = point.nSign;
|
||||
|
||||
//Free memory
|
||||
delete[] padfDescriptor;
|
||||
|
||||
//Copy descriptor values
|
||||
padfDescriptor = new double[DESC_SIZE];
|
||||
for (int i = 0; i < DESC_SIZE; i++)
|
||||
padfDescriptor[i] = point.padfDescriptor[i];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
int GDALFeaturePoint::GetX() { return nX; }
|
||||
void GDALFeaturePoint::SetX(int nX) { this->nX = nX; }
|
||||
|
||||
int GDALFeaturePoint::GetY() { return nY; }
|
||||
void GDALFeaturePoint::SetY(int nY) { this->nY = nY; }
|
||||
|
||||
int GDALFeaturePoint::GetScale() { return nScale; }
|
||||
void GDALFeaturePoint::SetScale(int nScale) { this->nScale = nScale; }
|
||||
|
||||
int GDALFeaturePoint::GetRadius() { return nRadius; }
|
||||
void GDALFeaturePoint::SetRadius(int nRadius) { this->nRadius = nRadius; }
|
||||
|
||||
int GDALFeaturePoint::GetSign() { return nSign; }
|
||||
void GDALFeaturePoint::SetSign(int nSign) { this->nSign = nSign; }
|
||||
|
||||
double& GDALFeaturePoint::operator [] (int nIndex)
|
||||
{
|
||||
if (nIndex < 0 || nIndex >= DESC_SIZE)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"Descriptor index is out of range");
|
||||
}
|
||||
|
||||
return padfDescriptor[nIndex];
|
||||
}
|
||||
|
||||
GDALFeaturePoint::~GDALFeaturePoint() {
|
||||
delete[] padfDescriptor;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* GDALSimpleSurf */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
GDALSimpleSURF::GDALSimpleSURF(int nOctaveStart, int nOctaveEnd)
|
||||
{
|
||||
this->octaveStart = nOctaveStart;
|
||||
this->octaveEnd = nOctaveEnd;
|
||||
|
||||
// Initialize Octave map with custom range
|
||||
poOctMap = new GDALOctaveMap(octaveStart, octaveEnd);
|
||||
}
|
||||
|
||||
CPLErr GDALSimpleSURF::ConvertRGBToLuminosity(
|
||||
GDALRasterBand *red, GDALRasterBand *green, GDALRasterBand *blue,
|
||||
int nXSize, int nYSize, double **padfImg, int nHeight, int nWidth)
|
||||
{
|
||||
const double forRed = 0.21;
|
||||
const double forGreen = 0.72;
|
||||
const double forBlue = 0.07;
|
||||
|
||||
if (red == NULL || green == NULL || blue == NULL)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"Raster bands are not specified");
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
if (nXSize > red->GetXSize() || nYSize > red->GetYSize())
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"Red band has less size than has been requested");
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
if (padfImg == NULL)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined, "Buffer isn't specified");
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
GDALDataType eRedType = red->GetRasterDataType();
|
||||
GDALDataType eGreenType = green->GetRasterDataType();
|
||||
GDALDataType eBlueType = blue->GetRasterDataType();
|
||||
|
||||
int dataRedSize = GDALGetDataTypeSize(eRedType) / 8;
|
||||
int dataGreenSize = GDALGetDataTypeSize(eGreenType) / 8;
|
||||
int dataBlueSize = GDALGetDataTypeSize(eBlueType) / 8;
|
||||
|
||||
void *paRedLayer = CPLMalloc(dataRedSize * nWidth * nHeight);
|
||||
void *paGreenLayer = CPLMalloc(dataGreenSize * nWidth * nHeight);
|
||||
void *paBlueLayer = CPLMalloc(dataBlueSize * nWidth * nHeight);
|
||||
|
||||
red->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paRedLayer, nWidth, nHeight, eRedType, 0, 0, NULL);
|
||||
green->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paGreenLayer, nWidth, nHeight, eGreenType, 0, 0, NULL);
|
||||
blue->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paBlueLayer, nWidth, nHeight, eBlueType, 0, 0, NULL);
|
||||
|
||||
double maxValue = 255.0;
|
||||
for (int row = 0; row < nHeight; row++)
|
||||
for (int col = 0; col < nWidth; col++)
|
||||
{
|
||||
// Get RGB values
|
||||
double dfRedVal = SRCVAL(paRedLayer, eRedType,
|
||||
nWidth * row + col * dataRedSize);
|
||||
double dfGreenVal = SRCVAL(paGreenLayer, eGreenType,
|
||||
nWidth * row + col * dataGreenSize);
|
||||
double dfBlueVal = SRCVAL(paBlueLayer, eBlueType,
|
||||
nWidth * row + col * dataBlueSize);
|
||||
// Compute luminosity value
|
||||
padfImg[row][col] = (
|
||||
dfRedVal * forRed +
|
||||
dfGreenVal * forGreen +
|
||||
dfBlueVal * forBlue) / maxValue;
|
||||
}
|
||||
|
||||
CPLFree(paRedLayer);
|
||||
CPLFree(paGreenLayer);
|
||||
CPLFree(paBlueLayer);
|
||||
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
std::vector<GDALFeaturePoint>*
|
||||
GDALSimpleSURF::ExtractFeaturePoints(GDALIntegralImage *poImg,
|
||||
double dfThreshold)
|
||||
{
|
||||
std::vector<GDALFeaturePoint>* poCollection =
|
||||
new std::vector<GDALFeaturePoint>();
|
||||
|
||||
//Calc Hessian values for layers
|
||||
poOctMap->ComputeMap(poImg);
|
||||
|
||||
//Search for exremum points
|
||||
for (int oct = octaveStart; oct <= octaveEnd; oct++)
|
||||
{
|
||||
for (int k = 0; k < GDALOctaveMap::INTERVALS - 2; k++)
|
||||
{
|
||||
GDALOctaveLayer *bot = poOctMap->pMap[oct - 1][k];
|
||||
GDALOctaveLayer *mid = poOctMap->pMap[oct - 1][k + 1];
|
||||
GDALOctaveLayer *top = poOctMap->pMap[oct - 1][k + 2];
|
||||
|
||||
for (int i = 0; i < mid->height; i++)
|
||||
{
|
||||
for (int j = 0; j < mid->width; j++)
|
||||
{
|
||||
if (poOctMap->PointIsExtremum(i, j, bot, mid, top, dfThreshold))
|
||||
{
|
||||
GDALFeaturePoint oFP(j, i, mid->scale,
|
||||
mid->radius, mid->signs[i][j]);
|
||||
SetDescriptor(&oFP, poImg);
|
||||
poCollection->push_back(oFP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return poCollection;
|
||||
}
|
||||
|
||||
|
||||
double GDALSimpleSURF::GetEuclideanDistance(
|
||||
GDALFeaturePoint &firstPoint, GDALFeaturePoint &secondPoint)
|
||||
{
|
||||
double sum = 0;
|
||||
|
||||
for (int i = 0; i < GDALFeaturePoint::DESC_SIZE; i++)
|
||||
sum += (firstPoint[i] - secondPoint[i]) * (firstPoint[i] - secondPoint[i]);
|
||||
|
||||
return sqrt(sum);
|
||||
}
|
||||
|
||||
void GDALSimpleSURF::NormalizeDistances(std::list<MatchedPointPairInfo> *poList)
|
||||
{
|
||||
double max = 0;
|
||||
|
||||
std::list<MatchedPointPairInfo>::iterator i;
|
||||
for (i = poList->begin(); i != poList->end(); i++)
|
||||
if ((*i).euclideanDist > max)
|
||||
max = (*i).euclideanDist;
|
||||
|
||||
if (max != 0)
|
||||
{
|
||||
for (i = poList->begin(); i != poList->end(); i++)
|
||||
(*i).euclideanDist /= max;
|
||||
}
|
||||
}
|
||||
|
||||
void GDALSimpleSURF::SetDescriptor(
|
||||
GDALFeaturePoint *poPoint, GDALIntegralImage *poImg)
|
||||
{
|
||||
// Affects to the descriptor area
|
||||
const int haarScale = 20;
|
||||
|
||||
// Side of the Haar wavelet
|
||||
int haarFilterSize = 2 * poPoint->GetScale();
|
||||
|
||||
// Length of the side of the descriptor area
|
||||
int descSide = haarScale * poPoint->GetScale();
|
||||
|
||||
// Side of the quadrant in 4x4 grid
|
||||
int quadStep = descSide / 4;
|
||||
|
||||
// Side of the sub-quadrant in 5x5 regular grid of quadrant
|
||||
int subQuadStep = quadStep / 5;
|
||||
|
||||
int leftTop_row = poPoint->GetY() - (descSide / 2);
|
||||
int leftTop_col = poPoint->GetX() - (descSide / 2);
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (int r = leftTop_row; r < leftTop_row + descSide; r += quadStep)
|
||||
for (int c = leftTop_col; c < leftTop_col + descSide; c += quadStep)
|
||||
{
|
||||
double dx = 0;
|
||||
double dy = 0;
|
||||
double abs_dx = 0;
|
||||
double abs_dy = 0;
|
||||
|
||||
for (int sub_r = r; sub_r < r + quadStep; sub_r += subQuadStep)
|
||||
for (int sub_c = c; sub_c < c + quadStep; sub_c += subQuadStep)
|
||||
{
|
||||
// Approximate center of sub quadrant
|
||||
int cntr_r = sub_r + subQuadStep / 2;
|
||||
int cntr_c = sub_c + subQuadStep / 2;
|
||||
|
||||
// Left top point for Haar wavelet computation
|
||||
int cur_r = cntr_r - haarFilterSize / 2;
|
||||
int cur_c = cntr_c - haarFilterSize / 2;
|
||||
|
||||
// Gradients
|
||||
double cur_dx = poImg->HaarWavelet_X(cur_r, cur_c, haarFilterSize);
|
||||
double cur_dy = poImg->HaarWavelet_Y(cur_r, cur_c, haarFilterSize);
|
||||
|
||||
dx += cur_dx;
|
||||
dy += cur_dy;
|
||||
abs_dx += fabs(cur_dx);
|
||||
abs_dy += fabs(cur_dy);
|
||||
}
|
||||
|
||||
// Fills point's descriptor
|
||||
(*poPoint)[count++] = dx;
|
||||
(*poPoint)[count++] = dy;
|
||||
(*poPoint)[count++] = abs_dx;
|
||||
(*poPoint)[count++] = abs_dy;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find corresponding points (equal points in two collections).
|
||||
*
|
||||
* @param poMatched Resulting collection for matched points
|
||||
* @param poFirstCollection Points on the first image
|
||||
* @param poSecondCollection Points on the second image
|
||||
* @param dfThreshold Value from 0 to 1. Threshold affects to number of
|
||||
* matched points. If threshold is higher, amount of corresponding
|
||||
* points is larger, and vice versa
|
||||
*
|
||||
* @note Typical threshold's value is 0,1. BUT it's a very approximate guide.
|
||||
* It can be 0,001 or even 1. This threshold provides direct adjustment
|
||||
* of point matching.
|
||||
* NOTICE that if threshold is lower, matches are more robust and correct, but number of
|
||||
* matched points is smaller. Therefore if algorithm performs many false
|
||||
* detections and produces bad results, reduce threshold.
|
||||
* Otherwise, if algorithm finds nothing, increase threshold.
|
||||
*
|
||||
* @return CE_None or CE_Failure if error occurs.
|
||||
*/
|
||||
|
||||
CPLErr GDALSimpleSURF::MatchFeaturePoints(
|
||||
std::vector<GDALFeaturePoint*> *poMatchPairs,
|
||||
std::vector<GDALFeaturePoint> *poFirstCollect,
|
||||
std::vector<GDALFeaturePoint> *poSecondCollect,
|
||||
double dfThreshold)
|
||||
{
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Validate parameters. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if (poMatchPairs == NULL)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"Matched points colection isn't specified");
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
if (poFirstCollect == NULL || poSecondCollect == NULL)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"Feature point collections are not specified");
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Matching algorithm. */
|
||||
/* ==================================================================== */
|
||||
// Affects to false matching pruning
|
||||
const double ratioThreshold = 0.8;
|
||||
|
||||
int len_1 = poFirstCollect->size();
|
||||
int len_2 = poSecondCollect->size();
|
||||
|
||||
int minLength = (len_1 < len_2) ? len_1 : len_2;
|
||||
|
||||
// Temporary pointers. Used to swap collections
|
||||
std::vector<GDALFeaturePoint> *p_1;
|
||||
std::vector<GDALFeaturePoint> *p_2;
|
||||
|
||||
bool isSwap = false;
|
||||
|
||||
// Assign p_1 - collection with minimal number of points
|
||||
if (minLength == len_2)
|
||||
{
|
||||
p_1 = poSecondCollect;
|
||||
p_2 = poFirstCollect;
|
||||
|
||||
int tmp = 0;
|
||||
tmp = len_1;
|
||||
len_1 = len_2;
|
||||
len_2 = tmp;
|
||||
isSwap = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assignment 'as is'
|
||||
p_1 = poFirstCollect;
|
||||
p_2 = poSecondCollect;
|
||||
isSwap = false;
|
||||
}
|
||||
|
||||
// Stores matched point indexes and
|
||||
// their euclidean distances
|
||||
std::list<MatchedPointPairInfo> *poPairInfoList =
|
||||
new std::list<MatchedPointPairInfo>();
|
||||
|
||||
// Flags that points in the 2nd collection are matched or not
|
||||
bool *alreadyMatched = new bool[len_2];
|
||||
for (int i = 0; i < len_2; i++)
|
||||
alreadyMatched[i] = false;
|
||||
|
||||
for (int i = 0; i < len_1; i++)
|
||||
{
|
||||
// Distance to the nearest point
|
||||
double bestDist = -1;
|
||||
// Index of the nearest point in p_2 collection
|
||||
int bestIndex = -1;
|
||||
|
||||
// Distance to the 2nd nearest point
|
||||
double bestDist_2 = -1;
|
||||
|
||||
// Find the nearest and 2nd nearest points
|
||||
for (int j = 0; j < len_2; j++)
|
||||
if (!alreadyMatched[j])
|
||||
if (p_1->at(i).GetSign() ==
|
||||
p_2->at(j).GetSign())
|
||||
{
|
||||
// Get distance between two feature points
|
||||
double curDist = GetEuclideanDistance(
|
||||
p_1->at(i), p_2->at(j));
|
||||
|
||||
if (bestDist == -1)
|
||||
{
|
||||
bestDist = curDist;
|
||||
bestIndex = j;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (curDist < bestDist)
|
||||
{
|
||||
bestDist = curDist;
|
||||
bestIndex = j;
|
||||
}
|
||||
}
|
||||
|
||||
// Findes the 2nd nearest point
|
||||
if (bestDist_2 < 0)
|
||||
bestDist_2 = curDist;
|
||||
else
|
||||
if (curDist > bestDist && curDist < bestDist_2)
|
||||
bestDist_2 = curDist;
|
||||
}
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* False matching pruning. */
|
||||
/* If ratio bestDist to bestDist_2 greater than 0.8 => */
|
||||
/* consider as false detection. */
|
||||
/* Otherwise, add points as matched pair. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
if (bestDist_2 > 0 && bestDist >= 0)
|
||||
if (bestDist / bestDist_2 < ratioThreshold)
|
||||
{
|
||||
MatchedPointPairInfo info(i, bestIndex, bestDist);
|
||||
poPairInfoList->push_back(info);
|
||||
alreadyMatched[bestIndex] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Pruning based on the provided threshold */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
NormalizeDistances(poPairInfoList);
|
||||
|
||||
std::list<MatchedPointPairInfo>::const_iterator iter;
|
||||
for (iter = poPairInfoList->begin(); iter != poPairInfoList->end(); iter++)
|
||||
{
|
||||
if ((*iter).euclideanDist <= dfThreshold)
|
||||
{
|
||||
int i_1 = (*iter).ind_1;
|
||||
int i_2 = (*iter).ind_2;
|
||||
|
||||
// Add copies into MatchedCollection
|
||||
if(!isSwap)
|
||||
{
|
||||
poMatchPairs->push_back( &(p_1->at(i_1)) );
|
||||
poMatchPairs->push_back( &(p_2->at(i_2)) );
|
||||
}
|
||||
else
|
||||
{
|
||||
poMatchPairs->push_back( &(p_2->at(i_2)) );
|
||||
poMatchPairs->push_back( &(p_1->at(i_1)) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
delete[] alreadyMatched;
|
||||
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
GDALSimpleSURF::~GDALSimpleSURF()
|
||||
{
|
||||
delete poOctMap;
|
||||
}
|
||||
|
||||
554
bazaar/plugin/gdal/alg/gdal_simplesurf.h
Normal file
554
bazaar/plugin/gdal/alg/gdal_simplesurf.h
Normal file
|
|
@ -0,0 +1,554 @@
|
|||
/******************************************************************************
|
||||
* Project: GDAL
|
||||
* Purpose: Correlator
|
||||
* Author: Andrew Migal, migal.drew@gmail.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2012, Andrew Migal
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @author Andrew Migal migal.drew@gmail.com
|
||||
* @brief Class for searching corresponding points on images.
|
||||
*/
|
||||
|
||||
#ifndef GDALSIMPLESURF_H_
|
||||
#define GDALSIMPLESURF_H_
|
||||
|
||||
#include "gdal_priv.h"
|
||||
#include "cpl_conv.h"
|
||||
#include <list>
|
||||
|
||||
/**
|
||||
* @brief Class of "feature point" in raster. Used by SURF-based algorithm.
|
||||
*
|
||||
* @details This point presents coordinates of distinctive pixel in image.
|
||||
* In computer vision, feature points - the most "strong" and "unique"
|
||||
* pixels (or areas) in picture, which can be distinguished from others.
|
||||
* For more details, see FAST corner detector, SIFT, SURF and similar algorithms.
|
||||
*/
|
||||
class GDALFeaturePoint
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Standard constructor. Initializes all parameters with negative numbers
|
||||
* and allocates memory for descriptor.
|
||||
*/
|
||||
GDALFeaturePoint();
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
* @param fp Copied instance of GDALFeaturePoint class
|
||||
*/
|
||||
GDALFeaturePoint(const GDALFeaturePoint& fp);
|
||||
|
||||
/**
|
||||
* Create instance of GDALFeaturePoint class
|
||||
*
|
||||
* @param nX X-coordinate (pixel)
|
||||
* @param nY Y-coordinate (line)
|
||||
* @param nScale Scale which contains this point (2, 4, 8, 16 and so on)
|
||||
* @param nRadius Half of the side of descriptor area
|
||||
* @param nSign Sign of Hessian determinant for this point
|
||||
*
|
||||
* @note This constructor normally is invoked by SURF-based algorithm,
|
||||
* which provides all necessary parameters.
|
||||
*/
|
||||
GDALFeaturePoint(int nX, int nY, int nScale, int nRadius, int nSign);
|
||||
virtual ~GDALFeaturePoint();
|
||||
|
||||
GDALFeaturePoint& operator=(const GDALFeaturePoint& point);
|
||||
|
||||
/**
|
||||
* Provide access to point's descriptor.
|
||||
*
|
||||
* @param nIndex Position of descriptor's value.
|
||||
* nIndex should be within range from 0 to DESC_SIZE (in current version - 64)
|
||||
*
|
||||
* @return Reference to value of descriptor in 'nIndex' position.
|
||||
* If index is out of range then behaviour is undefined.
|
||||
*/
|
||||
double& operator[](int nIndex);
|
||||
|
||||
// Descriptor length
|
||||
static const int DESC_SIZE = 64;
|
||||
|
||||
/**
|
||||
* Fetch X-coordinate (pixel) of point
|
||||
*
|
||||
* @return X-coordinate in pixels
|
||||
*/
|
||||
int GetX();
|
||||
|
||||
/**
|
||||
* Set X coordinate of point
|
||||
*
|
||||
* @param nX X coordinate in pixels
|
||||
*/
|
||||
void SetX(int nX);
|
||||
|
||||
/**
|
||||
* Fetch Y-coordinate (line) of point.
|
||||
*
|
||||
* @return Y-coordinate in pixels.
|
||||
*/
|
||||
int GetY();
|
||||
|
||||
/**
|
||||
* Set Y coordinate of point.
|
||||
*
|
||||
* @param nY Y coordinate in pixels.
|
||||
*/
|
||||
void SetY(int nY);
|
||||
|
||||
/**
|
||||
* Fetch scale of point.
|
||||
*
|
||||
* @return Scale for this point.
|
||||
*/
|
||||
int GetScale();
|
||||
|
||||
/**
|
||||
* Set scale of point.
|
||||
*
|
||||
* @param nScale Scale for this point.
|
||||
*/
|
||||
void SetScale(int nScale);
|
||||
|
||||
/**
|
||||
* Fetch radius of point.
|
||||
*
|
||||
* @return Radius for this point.
|
||||
*/
|
||||
int GetRadius();
|
||||
|
||||
/**
|
||||
* Set radius of point.
|
||||
*
|
||||
* @param nRadius Radius for this point.
|
||||
*/
|
||||
void SetRadius(int nRadius);
|
||||
|
||||
/**
|
||||
* Fetch sign of Hessian determinant of point.
|
||||
*
|
||||
* @return Sign for this point.
|
||||
*/
|
||||
int GetSign();
|
||||
|
||||
/**
|
||||
* Set sign of point.
|
||||
*
|
||||
* @param nSign Sign of Hessian determinant for this point.
|
||||
*/
|
||||
void SetSign(int nSign);
|
||||
|
||||
private:
|
||||
// Coordinates of point in image
|
||||
int nX;
|
||||
int nY;
|
||||
// --------------------
|
||||
int nScale;
|
||||
int nRadius;
|
||||
int nSign;
|
||||
// Descriptor array
|
||||
double *padfDescriptor;
|
||||
};
|
||||
|
||||
/**
|
||||
* @author Andrew Migal migal.drew@gmail.com
|
||||
* @brief Integral image class (summed area table).
|
||||
* @details Integral image is a table for fast computing the sum of
|
||||
* values in rectangular subarea. In more detail, for 2-dimensional array
|
||||
* of numbers this class provides capabilty to get sum of values in
|
||||
* rectangular arbitrary area with any size in constant time.
|
||||
* Integral image is constructed from grayscale picture.
|
||||
*/
|
||||
class GDALIntegralImage
|
||||
{
|
||||
public:
|
||||
GDALIntegralImage();
|
||||
virtual ~GDALIntegralImage();
|
||||
|
||||
/**
|
||||
* Compute integral image for specified array. Result is stored internally.
|
||||
*
|
||||
* @param padfImg Pointer to 2-dimensional array of values
|
||||
* @param nHeight Number of rows in array
|
||||
* @param nWidth Number of columns in array
|
||||
*/
|
||||
void Initialize(const double **padfImg, int nHeight, int nWidth);
|
||||
|
||||
/**
|
||||
* Fetch value of specified position in integral image.
|
||||
*
|
||||
* @param nRow Row of this position
|
||||
* @param nCol Column of this position
|
||||
*
|
||||
* @return Value in specified position or zero if parameters are out of range.
|
||||
*/
|
||||
double GetValue(int nRow, int nCol);
|
||||
|
||||
/**
|
||||
* Get sum of values in specified rectangular grid. Rectangle is constructed
|
||||
* from left top point.
|
||||
*
|
||||
* @param nRow Row of left top point of rectangle
|
||||
* @param nCol Column of left top point of rectangle
|
||||
* @param nWidth Width of rectangular area (number of columns)
|
||||
* @param nHeight Heigth of rectangular area (number of rows)
|
||||
*
|
||||
* @return Sum of values in specified grid.
|
||||
*/
|
||||
double GetRectangleSum(int nRow, int nCol, int nWidth, int nHeight);
|
||||
|
||||
/**
|
||||
* Get value of horizontal Haar wavelet in specified square grid.
|
||||
*
|
||||
* @param nRow Row of left top point of square
|
||||
* @param nCol Column of left top point of square
|
||||
* @param nSize Side of the square
|
||||
*
|
||||
* @return Value of horizontal Haar wavelet in specified square grid.
|
||||
*/
|
||||
double HaarWavelet_X(int nRow, int nCol, int nSize);
|
||||
|
||||
/**
|
||||
* Get value of vertical Haar wavelet in specified square grid.
|
||||
*
|
||||
* @param nRow Row of left top point of square
|
||||
* @param nCol Column of left top point of square
|
||||
* @param nSize Side of the square
|
||||
*
|
||||
* @return Value of vertical Haar wavelet in specified square grid.
|
||||
*/
|
||||
double HaarWavelet_Y(int nRow, int nCol, int nSize);
|
||||
|
||||
/**
|
||||
* Fetch height of integral image.
|
||||
*
|
||||
* @return Height of integral image (number of rows).
|
||||
*/
|
||||
int GetHeight();
|
||||
|
||||
/**
|
||||
* Fetch width of integral image.
|
||||
*
|
||||
* @return Width of integral image (number of columns).
|
||||
*/
|
||||
int GetWidth();
|
||||
|
||||
private:
|
||||
double **pMatrix;
|
||||
int nWidth;
|
||||
int nHeight;
|
||||
};
|
||||
|
||||
/**
|
||||
* @author Andrew Migal migal.drew@gmail.com
|
||||
* @brief Class for computation and storage of Hessian values in SURF-based algorithm.
|
||||
*
|
||||
* @details SURF-based algorithm normally uses this class for searching
|
||||
* feature points on raster images. Class also contains traces of Hessian matrices
|
||||
* to provide fast computations.
|
||||
*/
|
||||
class GDALOctaveLayer
|
||||
{
|
||||
public:
|
||||
GDALOctaveLayer();
|
||||
|
||||
/**
|
||||
* Create instance with provided parameters.
|
||||
*
|
||||
* @param nOctave Number of octave which contains this layer
|
||||
* @param nInterval Number of position in octave
|
||||
*
|
||||
* @note Normally constructor is invoked only by SURF-based algorithm.
|
||||
*/
|
||||
GDALOctaveLayer(int nOctave, int nInterval);
|
||||
virtual ~GDALOctaveLayer();
|
||||
|
||||
/**
|
||||
* Perform calculation of Hessian determinats and their signs
|
||||
* for specified integral image. Result is stored internally.
|
||||
*
|
||||
* @param poImg Integral image object, which provides all necessary
|
||||
* data for computation
|
||||
*
|
||||
* @note Normally method is invoked only by SURF-based algorithm.
|
||||
*/
|
||||
void ComputeLayer(GDALIntegralImage *poImg);
|
||||
|
||||
/**
|
||||
* Octave which contains this layer (1,2,3...)
|
||||
*/
|
||||
int octaveNum;
|
||||
/**
|
||||
* Length of the side of filter
|
||||
*/
|
||||
int filterSize;
|
||||
/**
|
||||
* Length of the border
|
||||
*/
|
||||
int radius;
|
||||
/**
|
||||
* Scale for this layer
|
||||
*/
|
||||
int scale;
|
||||
/**
|
||||
* Image width in pixels
|
||||
*/
|
||||
int width;
|
||||
/**
|
||||
* Image height in pixels
|
||||
*/
|
||||
int height;
|
||||
/**
|
||||
* Hessian values for image pixels
|
||||
*/
|
||||
double **detHessians;
|
||||
/**
|
||||
* Hessian signs for speeded matching
|
||||
*/
|
||||
int **signs;
|
||||
};
|
||||
|
||||
/**
|
||||
* @author Andrew Migal migal.drew@gmail.com
|
||||
* @brief Class for handling octave layers in SURF-based algorithm.
|
||||
* @details Class contains OctaveLayers and provides capability to construct octave space and distinguish
|
||||
* feature points. Normally this class is used only by SURF-based algorithm.
|
||||
*/
|
||||
class GDALOctaveMap
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create octave space. Octave numbers are start with one. (1, 2, 3, 4, ... )
|
||||
*
|
||||
* @param nOctaveStart Number of bottom octave
|
||||
* @param nOctaveEnd Number of top octave. Should be equal or greater than OctaveStart
|
||||
*/
|
||||
GDALOctaveMap(int nOctaveStart, int nOctaveEnd);
|
||||
virtual ~GDALOctaveMap();
|
||||
|
||||
/**
|
||||
* Calculate Hessian values for octave space
|
||||
* (for all stored octave layers) using specified integral image
|
||||
* @param poImg Integral image instance which provides necessary data
|
||||
* @see GDALOctaveLayer
|
||||
*/
|
||||
void ComputeMap(GDALIntegralImage *poImg);
|
||||
|
||||
/**
|
||||
* Method makes decision that specified point
|
||||
* in middle octave layer is maximum among all points
|
||||
* from 3x3x3 neighbourhood (surrounding points in
|
||||
* bottom, middle and top layers). Provided layers should be from the same octave's interval.
|
||||
* Detects feature points.
|
||||
*
|
||||
* @param row Row of point, which is candidate to be feature point
|
||||
* @param col Column of point, which is candidate to be feature point
|
||||
* @param bot Bottom octave layer
|
||||
* @param mid Middle octave layer
|
||||
* @param top Top octave layer
|
||||
* @param threshold Threshold for feature point recognition. Detected feature point
|
||||
* will have Hessian value greater than this provided threshold.
|
||||
*
|
||||
* @return TRUE if candidate was evaluated as feature point or FALSE otherwise.
|
||||
*/
|
||||
bool PointIsExtremum(int row, int col, GDALOctaveLayer *bot,
|
||||
GDALOctaveLayer *mid, GDALOctaveLayer *top, double threshold);
|
||||
|
||||
/**
|
||||
* 2-dimensional array of octave layers
|
||||
*/
|
||||
GDALOctaveLayer ***pMap;
|
||||
|
||||
/**
|
||||
* Value for constructing internal octave space
|
||||
*/
|
||||
static const int INTERVALS = 4;
|
||||
|
||||
/**
|
||||
* Number of bottom octave
|
||||
*/
|
||||
int octaveStart;
|
||||
|
||||
/**
|
||||
* Number of top octave. Should be equal or greater than OctaveStart
|
||||
*/
|
||||
int octaveEnd;
|
||||
};
|
||||
|
||||
/**
|
||||
* @author Andrew Migal migal.drew@gmail.com
|
||||
* @brief Class for searching corresponding points on images.
|
||||
* @details Provides capability for detection feature points
|
||||
* and finding equal points on different images.
|
||||
* Class implements simplified version of SURF algorithm (Speeded Up Robust Features).
|
||||
* As original, this realization is scale invariant, but sensitive to rotation.
|
||||
* Images should have similar rotation angles (maximum difference is up to 10-15 degrees),
|
||||
* otherwise algorithm produces incorrect and very unstable results.
|
||||
*/
|
||||
|
||||
class GDALSimpleSURF
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Class stores indexes of pair of point
|
||||
* and distance between them.
|
||||
*/
|
||||
class MatchedPointPairInfo
|
||||
{
|
||||
public:
|
||||
MatchedPointPairInfo(int nInd_1, int nInd_2, double dfDist)
|
||||
{
|
||||
ind_1 = nInd_1;
|
||||
ind_2 = nInd_2;
|
||||
euclideanDist = dfDist;
|
||||
}
|
||||
|
||||
int ind_1;
|
||||
int ind_2;
|
||||
double euclideanDist;
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* Prepare class according to specified parameters. Octave numbers affects
|
||||
* to amount of detected points and their robustness.
|
||||
* Range between bottom and top octaves also affects to required time of detection points
|
||||
* (if range is large, algorithm should perform more operations).
|
||||
* @param nOctaveStart Number of bottom octave. Octave numbers starts with one
|
||||
* @param nOctaveEnd Number of top octave. Should be equal or greater than OctaveStart
|
||||
*
|
||||
* @note
|
||||
* Every octave finds points with specific size. For small images
|
||||
* use small octave numbers, for high resolution - large.
|
||||
* For 1024x1024 images it's normal to use any octave numbers from range 1-6.
|
||||
* (for example, octave start - 1, octave end - 3, or octave start - 2, octave end - 2.)
|
||||
* For larger images, try 1-10 range or even higher.
|
||||
* Pay attention that number of detected point decreases quickly per octave
|
||||
* for particular image. Algorithm finds more points in case of small octave numbers.
|
||||
* If method detects nothing, reduce bottom bound of octave range.
|
||||
*
|
||||
* NOTICE that every octave requires time to compute. Use a little range
|
||||
* or only one octave if execution time is significant.
|
||||
*/
|
||||
GDALSimpleSURF(int nOctaveStart, int nOctaveEnd);
|
||||
virtual ~GDALSimpleSURF();
|
||||
|
||||
/**
|
||||
* Convert image with RGB channels to grayscale using "luminosity" method.
|
||||
* Result is used in SURF-based algorithm, but may be used anywhere where
|
||||
* grayscale images with nice contrast are required.
|
||||
*
|
||||
* @param red Image's red channel
|
||||
* @param green Image's green channel
|
||||
* @param blue Image's blue channel
|
||||
* @param nXSize Width of initial image
|
||||
* @param nYSize Height of initial image
|
||||
* @param padfImg Array for resulting grayscale image
|
||||
* @param nHeight Height of resulting image
|
||||
* @param nWidth Width of resulting image
|
||||
*
|
||||
* @return CE_None or CE_Failure if error occurs.
|
||||
*/
|
||||
static CPLErr ConvertRGBToLuminosity(
|
||||
GDALRasterBand *red,
|
||||
GDALRasterBand *green,
|
||||
GDALRasterBand *blue,
|
||||
int nXSize, int nYSize,
|
||||
double **padfImg, int nHeight, int nWidth);
|
||||
|
||||
/**
|
||||
* Find feature points using specified integral image.
|
||||
*
|
||||
* @param poImg Integral image to be used
|
||||
* @param dfThreshold Threshold for feature point recognition. Detected feature point
|
||||
* will have Hessian value greater than this provided threshold.
|
||||
*
|
||||
* @note Typical threshold's value is 0,001. But this value
|
||||
* can be various in each case and depends on image's nature.
|
||||
* For example, value can be 0.002 or 0.005.
|
||||
* Fill free to experiment with it.
|
||||
* If threshold is high, than number of detected feature points is small,
|
||||
* and vice versa.
|
||||
*/
|
||||
std::vector<GDALFeaturePoint>*
|
||||
ExtractFeaturePoints(GDALIntegralImage *poImg, double dfThreshold);
|
||||
|
||||
/**
|
||||
* Find corresponding points (equal points in two collections).
|
||||
*
|
||||
* @param poMatchPairs Resulting collection for matched points
|
||||
* @param poSecondCollect Points on the first image
|
||||
* @param poSecondCollect Points on the second image
|
||||
* @param dfThreshold Value from 0 to 1. Threshold affects to number of
|
||||
* matched points. If threshold is lower, amount of corresponding
|
||||
* points is larger, and vice versa
|
||||
*
|
||||
* @return CE_None or CE_Failure if error occurs.
|
||||
*/
|
||||
static CPLErr MatchFeaturePoints(
|
||||
std::vector<GDALFeaturePoint*> *poMatchPairs,
|
||||
std::vector<GDALFeaturePoint> *poFirstCollect,
|
||||
std::vector<GDALFeaturePoint> *poSecondCollect,
|
||||
double dfThreshold);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Compute euclidean distance between descriptors of two feature points.
|
||||
* It's used in comparison and matching of points.
|
||||
*
|
||||
* @param firstPoint First feature point to be compared
|
||||
* @param secondPoint Second feature point to be compared
|
||||
*
|
||||
* @return Euclidean distance between descriptors.
|
||||
*/
|
||||
static double GetEuclideanDistance(
|
||||
GDALFeaturePoint &firstPoint, GDALFeaturePoint &secondPoint);
|
||||
|
||||
/**
|
||||
* Set provided distance values to range from 0 to 1.
|
||||
*
|
||||
* @param poList List of distances to be normalized
|
||||
*/
|
||||
static void NormalizeDistances(std::list<MatchedPointPairInfo> *poList);
|
||||
|
||||
/**
|
||||
* Compute descriptor for specified feature point.
|
||||
*
|
||||
* @param poPoint Feature point instance
|
||||
* @param poImg image where feature point was found
|
||||
*/
|
||||
void SetDescriptor(GDALFeaturePoint *poPoint, GDALIntegralImage *poImg);
|
||||
|
||||
|
||||
private:
|
||||
int octaveStart;
|
||||
int octaveEnd;
|
||||
GDALOctaveMap *poOctMap;
|
||||
};
|
||||
|
||||
|
||||
#endif /* GDALSIMPLESURF_H_ */
|
||||
403
bazaar/plugin/gdal/alg/gdal_tps.cpp
Normal file
403
bazaar/plugin/gdal/alg/gdal_tps.cpp
Normal file
|
|
@ -0,0 +1,403 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdal_tps.cpp 29207 2015-05-18 17:23:45Z mloskot $
|
||||
*
|
||||
* Project: High Performance Image Reprojector
|
||||
* Purpose: Thin Plate Spline transformer (GDAL wrapper portion)
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
|
||||
* Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "thinplatespline.h"
|
||||
#include "gdal_alg.h"
|
||||
#include "gdal_alg_priv.h"
|
||||
#include "gdal_priv.h"
|
||||
#include "cpl_conv.h"
|
||||
#include "cpl_string.h"
|
||||
#include "cpl_atomic_ops.h"
|
||||
#include "cpl_multiproc.h"
|
||||
|
||||
CPL_CVSID("$Id: gdal_tps.cpp 29207 2015-05-18 17:23:45Z mloskot $");
|
||||
|
||||
CPL_C_START
|
||||
CPLXMLNode *GDALSerializeTPSTransformer( void *pTransformArg );
|
||||
void *GDALDeserializeTPSTransformer( CPLXMLNode *psTree );
|
||||
CPL_C_END
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GDALTransformerInfo sTI;
|
||||
|
||||
VizGeorefSpline2D *poForward;
|
||||
VizGeorefSpline2D *poReverse;
|
||||
int bForwardSolved;
|
||||
int bReverseSolved;
|
||||
|
||||
int bReversed;
|
||||
|
||||
int nGCPCount;
|
||||
GDAL_GCP *pasGCPList;
|
||||
|
||||
volatile int nRefCount;
|
||||
|
||||
} TPSTransformInfo;
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALCreateSimilarTPSTransformer() */
|
||||
/************************************************************************/
|
||||
|
||||
static
|
||||
void* GDALCreateSimilarTPSTransformer( void *hTransformArg, double dfRatioX, double dfRatioY )
|
||||
{
|
||||
VALIDATE_POINTER1( hTransformArg, "GDALCreateSimilarTPSTransformer", NULL );
|
||||
|
||||
TPSTransformInfo *psInfo = (TPSTransformInfo *) hTransformArg;
|
||||
|
||||
if( dfRatioX == 1.0 && dfRatioY == 1.0 )
|
||||
{
|
||||
/* We can just use a ref count, since using the source transformation */
|
||||
/* is thread-safe */
|
||||
CPLAtomicInc(&(psInfo->nRefCount));
|
||||
}
|
||||
else
|
||||
{
|
||||
GDAL_GCP *pasGCPList = GDALDuplicateGCPs( psInfo->nGCPCount,
|
||||
psInfo->pasGCPList );
|
||||
for(int i=0;i<psInfo->nGCPCount;i++)
|
||||
{
|
||||
pasGCPList[i].dfGCPPixel /= dfRatioX;
|
||||
pasGCPList[i].dfGCPLine /= dfRatioY;
|
||||
}
|
||||
psInfo = (TPSTransformInfo *) GDALCreateTPSTransformer( psInfo->nGCPCount, pasGCPList,
|
||||
psInfo->bReversed );
|
||||
GDALDeinitGCPs( psInfo->nGCPCount, pasGCPList );
|
||||
CPLFree( pasGCPList );
|
||||
}
|
||||
|
||||
return psInfo;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALCreateTPSTransformer() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Create Thin Plate Spline transformer from GCPs.
|
||||
*
|
||||
* The thin plate spline transformer produces exact transformation
|
||||
* at all control points and smoothly varying transformations between
|
||||
* control points with greatest influence from local control points.
|
||||
* It is suitable for for many applications not well modelled by polynomial
|
||||
* transformations.
|
||||
*
|
||||
* Creating the TPS transformer involves solving systems of linear equations
|
||||
* related to the number of control points involved. This solution is
|
||||
* computed within this function call. It can be quite an expensive operation
|
||||
* for large numbers of GCPs. For instance, for reference, it takes on the
|
||||
* order of 10s for 400 GCPs on a 2GHz Athlon processor.
|
||||
*
|
||||
* TPS Transformers are serializable.
|
||||
*
|
||||
* The GDAL Thin Plate Spline transformer is based on code provided by
|
||||
* Gilad Ronnen on behalf of VIZRT Inc (http://www.visrt.com). Incorporation
|
||||
* of the algorithm into GDAL was supported by the Centro di Ecologia Alpina
|
||||
* (http://www.cealp.it).
|
||||
*
|
||||
* @param nGCPCount the number of GCPs in pasGCPList.
|
||||
* @param pasGCPList an array of GCPs to be used as input.
|
||||
* @param bReversed set it to TRUE to compute the reversed transformation.
|
||||
*
|
||||
* @return the transform argument or NULL if creation fails.
|
||||
*/
|
||||
|
||||
void *GDALCreateTPSTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
|
||||
int bReversed )
|
||||
{
|
||||
return GDALCreateTPSTransformerInt(nGCPCount, pasGCPList, bReversed, NULL);
|
||||
}
|
||||
|
||||
static void GDALTPSComputeForwardInThread(void* pData)
|
||||
{
|
||||
TPSTransformInfo *psInfo = (TPSTransformInfo *)pData;
|
||||
psInfo->bForwardSolved = psInfo->poForward->solve() != 0;
|
||||
}
|
||||
|
||||
void *GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList,
|
||||
int bReversed, char** papszOptions )
|
||||
|
||||
{
|
||||
TPSTransformInfo *psInfo;
|
||||
int iGCP;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Allocate transform info. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
psInfo = (TPSTransformInfo *) CPLCalloc(sizeof(TPSTransformInfo),1);
|
||||
|
||||
psInfo->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList );
|
||||
psInfo->nGCPCount = nGCPCount;
|
||||
|
||||
psInfo->bReversed = bReversed;
|
||||
psInfo->poForward = new VizGeorefSpline2D( 2 );
|
||||
psInfo->poReverse = new VizGeorefSpline2D( 2 );
|
||||
|
||||
memcpy( psInfo->sTI.abySignature, GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE) );
|
||||
psInfo->sTI.pszClassName = "GDALTPSTransformer";
|
||||
psInfo->sTI.pfnTransform = GDALTPSTransform;
|
||||
psInfo->sTI.pfnCleanup = GDALDestroyTPSTransformer;
|
||||
psInfo->sTI.pfnSerialize = GDALSerializeTPSTransformer;
|
||||
psInfo->sTI.pfnCreateSimilar = GDALCreateSimilarTPSTransformer;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Attach all the points to the transformation. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
|
||||
{
|
||||
double afPL[2], afXY[2];
|
||||
|
||||
afPL[0] = pasGCPList[iGCP].dfGCPPixel;
|
||||
afPL[1] = pasGCPList[iGCP].dfGCPLine;
|
||||
afXY[0] = pasGCPList[iGCP].dfGCPX;
|
||||
afXY[1] = pasGCPList[iGCP].dfGCPY;
|
||||
|
||||
if( bReversed )
|
||||
{
|
||||
psInfo->poReverse->add_point( afPL[0], afPL[1], afXY );
|
||||
psInfo->poForward->add_point( afXY[0], afXY[1], afPL );
|
||||
}
|
||||
else
|
||||
{
|
||||
psInfo->poForward->add_point( afPL[0], afPL[1], afXY );
|
||||
psInfo->poReverse->add_point( afXY[0], afXY[1], afPL );
|
||||
}
|
||||
}
|
||||
|
||||
psInfo->nRefCount = 1;
|
||||
|
||||
int nThreads = 1;
|
||||
if( nGCPCount > 100 )
|
||||
{
|
||||
const char* pszWarpThreads = CSLFetchNameValue(papszOptions, "NUM_THREADS");
|
||||
if (pszWarpThreads == NULL)
|
||||
pszWarpThreads = CPLGetConfigOption("GDAL_NUM_THREADS", "1");
|
||||
if (EQUAL(pszWarpThreads, "ALL_CPUS"))
|
||||
nThreads = CPLGetNumCPUs();
|
||||
else
|
||||
nThreads = atoi(pszWarpThreads);
|
||||
}
|
||||
|
||||
if( nThreads > 1 )
|
||||
{
|
||||
/* Compute direct and reverse transforms in parallel */
|
||||
CPLJoinableThread* hThread = CPLCreateJoinableThread(GDALTPSComputeForwardInThread, psInfo);
|
||||
psInfo->bReverseSolved = psInfo->poReverse->solve() != 0;
|
||||
if( hThread != NULL )
|
||||
CPLJoinThread(hThread);
|
||||
else
|
||||
psInfo->bForwardSolved = psInfo->poForward->solve() != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
psInfo->bForwardSolved = psInfo->poForward->solve() != 0;
|
||||
psInfo->bReverseSolved = psInfo->poReverse->solve() != 0;
|
||||
}
|
||||
|
||||
if( !psInfo->bForwardSolved || !psInfo->bReverseSolved )
|
||||
{
|
||||
GDALDestroyTPSTransformer(psInfo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return psInfo;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALDestroyTPSTransformer() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Destroy TPS transformer.
|
||||
*
|
||||
* This function is used to destroy information about a GCP based
|
||||
* polynomial transformation created with GDALCreateTPSTransformer().
|
||||
*
|
||||
* @param pTransformArg the transform arg previously returned by
|
||||
* GDALCreateTPSTransformer().
|
||||
*/
|
||||
|
||||
void GDALDestroyTPSTransformer( void *pTransformArg )
|
||||
|
||||
{
|
||||
if( pTransformArg == NULL )
|
||||
return;
|
||||
|
||||
TPSTransformInfo *psInfo = (TPSTransformInfo *) pTransformArg;
|
||||
|
||||
if( CPLAtomicDec(&(psInfo->nRefCount)) == 0 )
|
||||
{
|
||||
delete psInfo->poForward;
|
||||
delete psInfo->poReverse;
|
||||
|
||||
GDALDeinitGCPs( psInfo->nGCPCount, psInfo->pasGCPList );
|
||||
CPLFree( psInfo->pasGCPList );
|
||||
|
||||
CPLFree( pTransformArg );
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALTPSTransform() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Transforms point based on GCP derived polynomial model.
|
||||
*
|
||||
* This function matches the GDALTransformerFunc signature, and can be
|
||||
* used to transform one or more points from pixel/line coordinates to
|
||||
* georeferenced coordinates (SrcToDst) or vice versa (DstToSrc).
|
||||
*
|
||||
* @param pTransformArg return value from GDALCreateTPSTransformer().
|
||||
* @param bDstToSrc TRUE if transformation is from the destination
|
||||
* (georeferenced) coordinates to pixel/line or FALSE when transforming
|
||||
* from pixel/line to georeferenced coordinates.
|
||||
* @param nPointCount the number of values in the x, y and z arrays.
|
||||
* @param x array containing the X values to be transformed.
|
||||
* @param y array containing the Y values to be transformed.
|
||||
* @param z array containing the Z values to be transformed.
|
||||
* @param panSuccess array in which a flag indicating success (TRUE) or
|
||||
* failure (FALSE) of the transformation are placed.
|
||||
*
|
||||
* @return TRUE.
|
||||
*/
|
||||
|
||||
int GDALTPSTransform( void *pTransformArg, int bDstToSrc,
|
||||
int nPointCount,
|
||||
double *x, double *y,
|
||||
CPL_UNUSED double *z,
|
||||
int *panSuccess )
|
||||
{
|
||||
VALIDATE_POINTER1( pTransformArg, "GDALTPSTransform", 0 );
|
||||
|
||||
int i;
|
||||
TPSTransformInfo *psInfo = (TPSTransformInfo *) pTransformArg;
|
||||
|
||||
for( i = 0; i < nPointCount; i++ )
|
||||
{
|
||||
double xy_out[2];
|
||||
|
||||
if( bDstToSrc )
|
||||
{
|
||||
psInfo->poReverse->get_point( x[i], y[i], xy_out );
|
||||
x[i] = xy_out[0];
|
||||
y[i] = xy_out[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
psInfo->poForward->get_point( x[i], y[i], xy_out );
|
||||
x[i] = xy_out[0];
|
||||
y[i] = xy_out[1];
|
||||
}
|
||||
panSuccess[i] = TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALSerializeTPSTransformer() */
|
||||
/************************************************************************/
|
||||
|
||||
CPLXMLNode *GDALSerializeTPSTransformer( void *pTransformArg )
|
||||
|
||||
{
|
||||
VALIDATE_POINTER1( pTransformArg, "GDALSerializeTPSTransformer", NULL );
|
||||
|
||||
CPLXMLNode *psTree;
|
||||
TPSTransformInfo *psInfo = static_cast<TPSTransformInfo *>(pTransformArg);
|
||||
|
||||
psTree = CPLCreateXMLNode( NULL, CXT_Element, "TPSTransformer" );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Serialize bReversed. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLCreateXMLElementAndValue(
|
||||
psTree, "Reversed",
|
||||
CPLString().Printf( "%d", psInfo->bReversed ) );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Attach GCP List. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( psInfo->nGCPCount > 0 )
|
||||
{
|
||||
GDALSerializeGCPListToXML( psTree,
|
||||
psInfo->pasGCPList,
|
||||
psInfo->nGCPCount,
|
||||
NULL );
|
||||
}
|
||||
|
||||
return psTree;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALDeserializeTPSTransformer() */
|
||||
/************************************************************************/
|
||||
|
||||
void *GDALDeserializeTPSTransformer( CPLXMLNode *psTree )
|
||||
|
||||
{
|
||||
GDAL_GCP *pasGCPList = 0;
|
||||
int nGCPCount = 0;
|
||||
void *pResult;
|
||||
int bReversed;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Check for GCPs. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLXMLNode *psGCPList = CPLGetXMLNode( psTree, "GCPList" );
|
||||
|
||||
if( psGCPList != NULL )
|
||||
{
|
||||
GDALDeserializeGCPListFromXML( psGCPList,
|
||||
&pasGCPList,
|
||||
&nGCPCount,
|
||||
NULL );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Get other flags. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
bReversed = atoi(CPLGetXMLValue(psTree,"Reversed","0"));
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Generate transformation. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
pResult = GDALCreateTPSTransformer( nGCPCount, pasGCPList, bReversed );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Cleanup GCP copy. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GDALDeinitGCPs( nGCPCount, pasGCPList );
|
||||
CPLFree( pasGCPList );
|
||||
|
||||
return pResult;
|
||||
}
|
||||
172
bazaar/plugin/gdal/alg/gdalchecksum.cpp
Normal file
172
bazaar/plugin/gdal/alg/gdalchecksum.cpp
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdalchecksum.cpp 27044 2014-03-16 23:41:27Z rouault $
|
||||
*
|
||||
* Project: GDAL
|
||||
* Purpose: Compute simple checksum for a region of image data.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2003, Frank Warmerdam
|
||||
* Copyright (c) 2007-2008, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_alg.h"
|
||||
#include "cpl_conv.h"
|
||||
|
||||
CPL_CVSID("$Id: gdalchecksum.cpp 27044 2014-03-16 23:41:27Z rouault $");
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALChecksumImage() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Compute checksum for image region.
|
||||
*
|
||||
* Computes a 16bit (0-65535) checksum from a region of raster data on a GDAL
|
||||
* supported band. Floating point data is converted to 32bit integer
|
||||
* so decimal portions of such raster data will not affect the checksum.
|
||||
* Real and Imaginary components of complex bands influence the result.
|
||||
*
|
||||
* @param hBand the raster band to read from.
|
||||
* @param nXOff pixel offset of window to read.
|
||||
* @param nYOff line offset of window to read.
|
||||
* @param nXSize pixel size of window to read.
|
||||
* @param nYSize line size of window to read.
|
||||
*
|
||||
* @return Checksum value.
|
||||
*/
|
||||
|
||||
int CPL_STDCALL
|
||||
GDALChecksumImage( GDALRasterBandH hBand,
|
||||
int nXOff, int nYOff, int nXSize, int nYSize )
|
||||
|
||||
{
|
||||
VALIDATE_POINTER1( hBand, "GDALChecksumImage", 0 );
|
||||
|
||||
const static int anPrimes[11] =
|
||||
{ 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43 };
|
||||
|
||||
int iLine, i, nChecksum = 0, iPrime = 0, nCount;
|
||||
GDALDataType eDataType = GDALGetRasterDataType( hBand );
|
||||
int bComplex = GDALDataTypeIsComplex( eDataType );
|
||||
|
||||
if (eDataType == GDT_Float32 || eDataType == GDT_Float64 ||
|
||||
eDataType == GDT_CFloat32 || eDataType == GDT_CFloat64)
|
||||
{
|
||||
double* padfLineData;
|
||||
GDALDataType eDstDataType = (bComplex) ? GDT_CFloat64 : GDT_Float64;
|
||||
|
||||
padfLineData = (double *) VSIMalloc2(nXSize, sizeof(double) * 2);
|
||||
if (padfLineData == NULL)
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_OutOfMemory,
|
||||
"VSIMalloc2(): Out of memory in GDALChecksumImage. "
|
||||
"Checksum value couldn't be computed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for( iLine = nYOff; iLine < nYOff + nYSize; iLine++ )
|
||||
{
|
||||
if (GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1,
|
||||
padfLineData, nXSize, 1, eDstDataType, 0, 0 ) != CE_None)
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_FileIO,
|
||||
"Checksum value couldn't be computed due to I/O read error.\n");
|
||||
break;
|
||||
}
|
||||
nCount = (bComplex) ? nXSize * 2 : nXSize;
|
||||
|
||||
for( i = 0; i < nCount; i++ )
|
||||
{
|
||||
double dfVal = padfLineData[i];
|
||||
int nVal;
|
||||
if (CPLIsNan(dfVal) || CPLIsInf(dfVal))
|
||||
{
|
||||
/* Most compilers seem to cast NaN or Inf to 0x80000000. */
|
||||
/* but VC7 is an exception. So we force the result */
|
||||
/* of such a cast */
|
||||
nVal = 0x80000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Standard behaviour of GDALCopyWords when converting */
|
||||
/* from floating point to Int32 */
|
||||
dfVal += 0.5;
|
||||
|
||||
if( dfVal < -2147483647.0 )
|
||||
nVal = -2147483647;
|
||||
else if( dfVal > 2147483647 )
|
||||
nVal = 2147483647;
|
||||
else
|
||||
nVal = (GInt32) floor(dfVal);
|
||||
}
|
||||
|
||||
nChecksum += (nVal % anPrimes[iPrime++]);
|
||||
if( iPrime > 10 )
|
||||
iPrime = 0;
|
||||
|
||||
nChecksum &= 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
CPLFree(padfLineData);
|
||||
}
|
||||
else
|
||||
{
|
||||
int *panLineData;
|
||||
GDALDataType eDstDataType = (bComplex) ? GDT_CInt32 : GDT_Int32;
|
||||
|
||||
panLineData = (GInt32 *) VSIMalloc2(nXSize, sizeof(GInt32) * 2);
|
||||
if (panLineData == NULL)
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_OutOfMemory,
|
||||
"VSIMalloc2(): Out of memory in GDALChecksumImage. "
|
||||
"Checksum value couldn't be computed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for( iLine = nYOff; iLine < nYOff + nYSize; iLine++ )
|
||||
{
|
||||
if (GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1,
|
||||
panLineData, nXSize, 1, eDstDataType, 0, 0 ) != CE_None)
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_FileIO,
|
||||
"Checksum value couldn't be computed due to I/O read error.\n");
|
||||
break;
|
||||
}
|
||||
nCount = (bComplex) ? nXSize * 2 : nXSize;
|
||||
|
||||
for( i = 0; i < nCount; i++ )
|
||||
{
|
||||
nChecksum += (panLineData[i] % anPrimes[iPrime++]);
|
||||
if( iPrime > 10 )
|
||||
iPrime = 0;
|
||||
|
||||
nChecksum &= 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
CPLFree( panLineData );
|
||||
}
|
||||
|
||||
return nChecksum;
|
||||
}
|
||||
|
||||
418
bazaar/plugin/gdal/alg/gdalcutline.cpp
Normal file
418
bazaar/plugin/gdal/alg/gdalcutline.cpp
Normal file
|
|
@ -0,0 +1,418 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdalcutline.cpp 28223 2014-12-26 11:28:03Z goatbar $
|
||||
*
|
||||
* Project: High Performance Image Reprojector
|
||||
* Purpose: Implement cutline/blend mask generator.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2008, Frank Warmerdam <warmerdam@pobox.com>
|
||||
* Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdalwarper.h"
|
||||
#include "gdal_alg.h"
|
||||
#include "ogr_api.h"
|
||||
#include "ogr_geos.h"
|
||||
#include "ogr_geometry.h"
|
||||
#include "cpl_string.h"
|
||||
|
||||
CPL_CVSID("$Id: gdalcutline.cpp 28223 2014-12-26 11:28:03Z goatbar $");
|
||||
|
||||
/************************************************************************/
|
||||
/* BlendMaskGenerator() */
|
||||
/************************************************************************/
|
||||
|
||||
static CPLErr
|
||||
BlendMaskGenerator(
|
||||
#ifndef HAVE_GEOS
|
||||
CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
|
||||
CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
|
||||
CPL_UNUSED GByte *pabyPolyMask,
|
||||
CPL_UNUSED float *pafValidityMask,
|
||||
CPL_UNUSED OGRGeometryH hPolygon,
|
||||
CPL_UNUSED double dfBlendDist
|
||||
#else
|
||||
int nXOff, int nYOff, int nXSize, int nYSize,
|
||||
GByte *pabyPolyMask, float *pafValidityMask,
|
||||
OGRGeometryH hPolygon, double dfBlendDist
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#ifndef HAVE_GEOS
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Blend distance support not available without the GEOS library.");
|
||||
return CE_Failure;
|
||||
|
||||
#else /* HAVE_GEOS */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Convert the polygon into a collection of lines so that we */
|
||||
/* measure distance from the edge even on the inside. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
OGRGeometry *poLines
|
||||
= OGRGeometryFactory::forceToMultiLineString(
|
||||
((OGRGeometry *) hPolygon)->clone() );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Prepare a clipping polygon a bit bigger than the area of */
|
||||
/* interest in the hopes of simplifying the cutline down to */
|
||||
/* stuff that will be relavent for this area of interest. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLString osClipRectWKT;
|
||||
|
||||
osClipRectWKT.Printf( "POLYGON((%g %g,%g %g,%g %g,%g %g,%g %g))",
|
||||
nXOff - (dfBlendDist+1),
|
||||
nYOff - (dfBlendDist+1),
|
||||
nXOff + nXSize + (dfBlendDist+1),
|
||||
nYOff - (dfBlendDist+1),
|
||||
nXOff + nXSize + (dfBlendDist+1),
|
||||
nYOff + nYSize + (dfBlendDist+1),
|
||||
nXOff - (dfBlendDist+1),
|
||||
nYOff + nYSize + (dfBlendDist+1),
|
||||
nXOff - (dfBlendDist+1),
|
||||
nYOff - (dfBlendDist+1) );
|
||||
|
||||
OGRPolygon *poClipRect = NULL;
|
||||
char *pszWKT = (char *) osClipRectWKT.c_str();
|
||||
|
||||
OGRGeometryFactory::createFromWkt( &pszWKT, NULL,
|
||||
(OGRGeometry**) (&poClipRect) );
|
||||
|
||||
if( poClipRect )
|
||||
{
|
||||
|
||||
/***** if it doesnt intersect the polym zero the mask and return *****/
|
||||
|
||||
if ( ! ((OGRGeometry *) hPolygon)->Intersects( poClipRect ) )
|
||||
{
|
||||
|
||||
memset( pafValidityMask, 0, sizeof(float) * nXSize * nYSize );
|
||||
|
||||
delete poLines;
|
||||
delete poClipRect;
|
||||
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
/***** if it doesnt intersect the line at all just return *****/
|
||||
|
||||
else if ( ! ((OGRGeometry *) poLines)->Intersects( poClipRect ) )
|
||||
{
|
||||
delete poLines;
|
||||
delete poClipRect;
|
||||
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
OGRGeometry *poClippedLines =
|
||||
poLines->Intersection( poClipRect );
|
||||
delete poLines;
|
||||
poLines = poClippedLines;
|
||||
delete poClipRect;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Convert our polygon into GEOS format, and compute an */
|
||||
/* envelope to accelerate later distance operations. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
OGREnvelope sEnvelope;
|
||||
int iXMin, iYMin, iXMax, iYMax;
|
||||
GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
|
||||
GEOSGeom poGEOSPoly;
|
||||
|
||||
poGEOSPoly = poLines->exportToGEOS(hGEOSCtxt);
|
||||
OGR_G_GetEnvelope( hPolygon, &sEnvelope );
|
||||
|
||||
delete poLines;
|
||||
|
||||
/***** this check was already done in the calling *****/
|
||||
/***** function and should never be true *****/
|
||||
|
||||
/*if( sEnvelope.MinY - dfBlendDist > nYOff+nYSize
|
||||
|| sEnvelope.MaxY + dfBlendDist < nYOff
|
||||
|| sEnvelope.MinX - dfBlendDist > nXOff+nXSize
|
||||
|| sEnvelope.MaxX + dfBlendDist < nXOff )
|
||||
return CE_None;
|
||||
*/
|
||||
|
||||
|
||||
iXMin = MAX(0,(int) floor(sEnvelope.MinX - dfBlendDist - nXOff));
|
||||
iXMax = MIN(nXSize, (int) ceil(sEnvelope.MaxX + dfBlendDist - nXOff));
|
||||
iYMin = MAX(0,(int) floor(sEnvelope.MinY - dfBlendDist - nYOff));
|
||||
iYMax = MIN(nYSize, (int) ceil(sEnvelope.MaxY + dfBlendDist - nYOff));
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Loop over potential area within blend line distance, */
|
||||
/* processing each pixel. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int iY, iX;
|
||||
double dfLastDist;
|
||||
|
||||
for( iY = 0; iY < nYSize; iY++ )
|
||||
{
|
||||
dfLastDist = 0.0;
|
||||
|
||||
for( iX = 0; iX < nXSize; iX++ )
|
||||
{
|
||||
if( iX < iXMin || iX >= iXMax
|
||||
|| iY < iYMin || iY > iYMax
|
||||
|| dfLastDist > dfBlendDist + 1.5 )
|
||||
{
|
||||
if( pabyPolyMask[iX + iY * nXSize] == 0 )
|
||||
pafValidityMask[iX + iY * nXSize] = 0.0;
|
||||
|
||||
dfLastDist -= 1.0;
|
||||
continue;
|
||||
}
|
||||
|
||||
double dfDist, dfRatio;
|
||||
CPLString osPointWKT;
|
||||
GEOSGeom poGEOSPoint;
|
||||
|
||||
osPointWKT.Printf( "POINT(%d.5 %d.5)", iX + nXOff, iY + nYOff );
|
||||
poGEOSPoint = GEOSGeomFromWKT_r( hGEOSCtxt, osPointWKT );
|
||||
|
||||
GEOSDistance_r( hGEOSCtxt, poGEOSPoly, poGEOSPoint, &dfDist );
|
||||
GEOSGeom_destroy_r( hGEOSCtxt, poGEOSPoint );
|
||||
|
||||
dfLastDist = dfDist;
|
||||
|
||||
if( dfDist > dfBlendDist )
|
||||
{
|
||||
if( pabyPolyMask[iX + iY * nXSize] == 0 )
|
||||
pafValidityMask[iX + iY * nXSize] = 0.0;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if( pabyPolyMask[iX + iY * nXSize] == 0 )
|
||||
{
|
||||
/* outside */
|
||||
dfRatio = 0.5 - (dfDist / dfBlendDist) * 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* inside */
|
||||
dfRatio = 0.5 + (dfDist / dfBlendDist) * 0.5;
|
||||
}
|
||||
|
||||
pafValidityMask[iX + iY * nXSize] *= (float)dfRatio;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Cleanup */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GEOSGeom_destroy_r( hGEOSCtxt, poGEOSPoly );
|
||||
OGRGeometry::freeGEOSContext( hGEOSCtxt );
|
||||
|
||||
return CE_None;
|
||||
|
||||
#endif /* HAVE_GEOS */
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* CutlineTransformer() */
|
||||
/* */
|
||||
/* A simple transformer for the cutline that just offsets */
|
||||
/* relative to the current chunk. */
|
||||
/************************************************************************/
|
||||
|
||||
static int CutlineTransformer( void *pTransformArg,
|
||||
int bDstToSrc,
|
||||
int nPointCount,
|
||||
double *x,
|
||||
double *y,
|
||||
CPL_UNUSED double *z,
|
||||
CPL_UNUSED int *panSuccess )
|
||||
{
|
||||
int nXOff = ((int *) pTransformArg)[0];
|
||||
int nYOff = ((int *) pTransformArg)[1];
|
||||
int i;
|
||||
|
||||
if( bDstToSrc )
|
||||
{
|
||||
nXOff *= -1;
|
||||
nYOff *= -1;
|
||||
}
|
||||
|
||||
for( i = 0; i < nPointCount; i++ )
|
||||
{
|
||||
x[i] -= nXOff;
|
||||
y[i] -= nYOff;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALWarpCutlineMasker() */
|
||||
/* */
|
||||
/* This function will generate a source mask based on a */
|
||||
/* provided cutline, and optional blend distance. */
|
||||
/************************************************************************/
|
||||
|
||||
CPLErr
|
||||
GDALWarpCutlineMasker( void *pMaskFuncArg,
|
||||
CPL_UNUSED int nBandCount,
|
||||
CPL_UNUSED GDALDataType eType,
|
||||
int nXOff, int nYOff, int nXSize, int nYSize,
|
||||
GByte ** /*ppImageData */,
|
||||
int bMaskIsFloat, void *pValidityMask )
|
||||
|
||||
{
|
||||
GDALWarpOptions *psWO = (GDALWarpOptions *) pMaskFuncArg;
|
||||
float *pafMask = (float *) pValidityMask;
|
||||
CPLErr eErr;
|
||||
GDALDriverH hMemDriver;
|
||||
|
||||
if( nXSize < 1 || nYSize < 1 )
|
||||
return CE_None;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Do some minimal checking. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( !bMaskIsFloat )
|
||||
{
|
||||
CPLAssert( FALSE );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
if( psWO == NULL || psWO->hCutline == NULL )
|
||||
{
|
||||
CPLAssert( FALSE );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
hMemDriver = GDALGetDriverByName("MEM");
|
||||
if (hMemDriver == NULL)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined, "GDALWarpCutlineMasker needs MEM driver");
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Check the polygon. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
OGRGeometryH hPolygon = (OGRGeometryH) psWO->hCutline;
|
||||
OGREnvelope sEnvelope;
|
||||
|
||||
if( wkbFlatten(OGR_G_GetGeometryType(hPolygon)) != wkbPolygon
|
||||
&& wkbFlatten(OGR_G_GetGeometryType(hPolygon)) != wkbMultiPolygon )
|
||||
{
|
||||
CPLAssert( FALSE );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
OGR_G_GetEnvelope( hPolygon, &sEnvelope );
|
||||
|
||||
if( sEnvelope.MaxX + psWO->dfCutlineBlendDist < nXOff
|
||||
|| sEnvelope.MinX - psWO->dfCutlineBlendDist > nXOff + nXSize
|
||||
|| sEnvelope.MaxY + psWO->dfCutlineBlendDist < nYOff
|
||||
|| sEnvelope.MinY - psWO->dfCutlineBlendDist > nYOff + nYSize )
|
||||
{
|
||||
// We are far from the blend line - everything is masked to zero.
|
||||
// It would be nice to realize no work is required for this whole
|
||||
// chunk!
|
||||
memset( pafMask, 0, sizeof(float) * nXSize * nYSize );
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create a byte buffer into which we can burn the */
|
||||
/* mask polygon and wrap it up as a memory dataset. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GByte *pabyPolyMask = (GByte *) CPLCalloc( nXSize, nYSize );
|
||||
GDALDatasetH hMemDS;
|
||||
double adfGeoTransform[6] = { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 };
|
||||
|
||||
char szDataPointer[100];
|
||||
char *apszOptions[] = { szDataPointer, NULL };
|
||||
|
||||
memset( szDataPointer, 0, sizeof(szDataPointer) );
|
||||
sprintf( szDataPointer, "DATAPOINTER=" );
|
||||
CPLPrintPointer( szDataPointer+strlen(szDataPointer),
|
||||
pabyPolyMask,
|
||||
sizeof(szDataPointer) - strlen(szDataPointer) );
|
||||
|
||||
hMemDS = GDALCreate( hMemDriver, "warp_temp",
|
||||
nXSize, nYSize, 0, GDT_Byte, NULL );
|
||||
GDALAddBand( hMemDS, GDT_Byte, apszOptions );
|
||||
GDALSetGeoTransform( hMemDS, adfGeoTransform );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Burn the polygon into the mask with 1.0 values. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int nTargetBand = 1;
|
||||
double dfBurnValue = 255.0;
|
||||
int anXYOff[2];
|
||||
char **papszRasterizeOptions = NULL;
|
||||
|
||||
|
||||
if( CSLFetchBoolean( psWO->papszWarpOptions, "CUTLINE_ALL_TOUCHED", FALSE ))
|
||||
papszRasterizeOptions =
|
||||
CSLSetNameValue( papszRasterizeOptions, "ALL_TOUCHED", "TRUE" );
|
||||
|
||||
anXYOff[0] = nXOff;
|
||||
anXYOff[1] = nYOff;
|
||||
|
||||
eErr =
|
||||
GDALRasterizeGeometries( hMemDS, 1, &nTargetBand,
|
||||
1, &hPolygon,
|
||||
CutlineTransformer, anXYOff,
|
||||
&dfBurnValue, papszRasterizeOptions,
|
||||
NULL, NULL );
|
||||
|
||||
CSLDestroy( papszRasterizeOptions );
|
||||
|
||||
// Close and ensure data flushed to underlying array.
|
||||
GDALClose( hMemDS );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* In the case with no blend distance, we just apply this as a */
|
||||
/* mask, zeroing out everything outside the polygon. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( psWO->dfCutlineBlendDist == 0.0 )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = nXSize * nYSize - 1; i >= 0; i-- )
|
||||
{
|
||||
if( pabyPolyMask[i] == 0 )
|
||||
((float *) pValidityMask)[i] = 0.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
eErr = BlendMaskGenerator( nXOff, nYOff, nXSize, nYSize,
|
||||
pabyPolyMask, (float *) pValidityMask,
|
||||
hPolygon, psWO->dfCutlineBlendDist );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Clean up. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLFree( pabyPolyMask );
|
||||
|
||||
return eErr;
|
||||
}
|
||||
656
bazaar/plugin/gdal/alg/gdaldither.cpp
Normal file
656
bazaar/plugin/gdal/alg/gdaldither.cpp
Normal file
|
|
@ -0,0 +1,656 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdaldither.cpp 28085 2014-12-07 14:36:00Z rouault $
|
||||
*
|
||||
* Project: CIETMap Phase 2
|
||||
* Purpose: Convert RGB (24bit) to a pseudo-colored approximation using
|
||||
* Floyd-Steinberg dithering (error diffusion).
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2001, Frank Warmerdam
|
||||
* Copyright (c) 2007, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* [1] Floyd-Steinberg dither:
|
||||
* I should point out that the actual fractions we used were, assuming
|
||||
* you are at X, moving left to right:
|
||||
*
|
||||
* X 7/16
|
||||
* 3/16 5/16 1/16
|
||||
*
|
||||
* Note that the error goes to four neighbors, not three. I think this
|
||||
* will probably do better (at least for black and white) than the
|
||||
* 3/8-3/8-1/4 distribution, at the cost of greater processing. I have
|
||||
* seen the 3/8-3/8-1/4 distribution described as "our" algorithm before,
|
||||
* but I have no idea who the credit really belongs to.
|
||||
* --
|
||||
* Lou Steinberg
|
||||
*
|
||||
*/
|
||||
|
||||
#include "gdal_priv.h"
|
||||
#include "gdal_alg.h"
|
||||
#include "gdal_alg_priv.h"
|
||||
|
||||
#if defined(__x86_64) || defined(_M_X64)
|
||||
#define USE_SSE2
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSE2
|
||||
|
||||
#include <emmintrin.h>
|
||||
#define CAST_PCT(x) ((GByte*)x)
|
||||
#define ALIGN_INT_ARRAY_ON_16_BYTE(x) ( (((GPtrDiff_t)(x) % 16) != 0 ) ? (int*)((GByte*)(x) + 16 - ((GPtrDiff_t)(x) % 16)) : (x) )
|
||||
|
||||
#else
|
||||
|
||||
#define CAST_PCT(x) x
|
||||
|
||||
#endif
|
||||
|
||||
#define MAKE_COLOR_CODE(r,g,b) ((r)|((g)<<8)|((b)<<16))
|
||||
|
||||
CPL_CVSID("$Id: gdaldither.cpp 28085 2014-12-07 14:36:00Z rouault $");
|
||||
|
||||
static void FindNearestColor( int nColors, int *panPCT, GByte *pabyColorMap,
|
||||
int nCLevels );
|
||||
static int FindNearestColor( int nColors, int *panPCT,
|
||||
int nRedValue, int nGreenValue, int nBlueValue );
|
||||
|
||||
/* Structure for a hashmap from a color code to a color index of the color table */
|
||||
typedef struct /* NOTE: if changing the size of this structure, edit MEDIAN_CUT_AND_DITHER_BUFFER_SIZE_65536 */
|
||||
{
|
||||
GUInt32 nColorCode;
|
||||
GUInt32 nColorCode2;
|
||||
GUInt32 nColorCode3;
|
||||
GByte nIndex;
|
||||
GByte nIndex2;
|
||||
GByte nIndex3;
|
||||
GByte nPadding;
|
||||
} ColorIndex;
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALDitherRGB2PCT() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* 24bit to 8bit conversion with dithering.
|
||||
*
|
||||
* This functions utilizes Floyd-Steinberg dithering in the process of
|
||||
* converting a 24bit RGB image into a pseudocolored 8bit image using a
|
||||
* provided color table.
|
||||
*
|
||||
* The red, green and blue input bands do not necessarily need to come
|
||||
* from the same file, but they must be the same width and height. They will
|
||||
* be clipped to 8bit during reading, so non-eight bit bands are generally
|
||||
* inappropriate. Likewise the hTarget band will be written with 8bit values
|
||||
* and must match the width and height of the source bands.
|
||||
*
|
||||
* The color table cannot have more than 256 entries.
|
||||
*
|
||||
* @param hRed Red input band.
|
||||
* @param hGreen Green input band.
|
||||
* @param hBlue Blue input band.
|
||||
* @param hTarget Output band.
|
||||
* @param hColorTable the color table to use with the output band.
|
||||
* @param pfnProgress callback for reporting algorithm progress matching the
|
||||
* GDALProgressFunc() semantics. May be NULL.
|
||||
* @param pProgressArg callback argument passed to pfnProgress.
|
||||
*
|
||||
* @return CE_None on success or CE_Failure if an error occurs.
|
||||
*/
|
||||
|
||||
int CPL_STDCALL
|
||||
GDALDitherRGB2PCT( GDALRasterBandH hRed,
|
||||
GDALRasterBandH hGreen,
|
||||
GDALRasterBandH hBlue,
|
||||
GDALRasterBandH hTarget,
|
||||
GDALColorTableH hColorTable,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg )
|
||||
|
||||
{
|
||||
return GDALDitherRGB2PCTInternal( hRed, hGreen, hBlue, hTarget,
|
||||
hColorTable, 5, NULL, TRUE,
|
||||
pfnProgress, pProgressArg );
|
||||
}
|
||||
|
||||
int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
|
||||
GDALRasterBandH hGreen,
|
||||
GDALRasterBandH hBlue,
|
||||
GDALRasterBandH hTarget,
|
||||
GDALColorTableH hColorTable,
|
||||
int nBits,
|
||||
GInt16* pasDynamicColorMap, /* NULL or at least 256 * 256 * 256 * sizeof(GInt16) bytes */
|
||||
int bDither,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg )
|
||||
{
|
||||
VALIDATE_POINTER1( hRed, "GDALDitherRGB2PCT", CE_Failure );
|
||||
VALIDATE_POINTER1( hGreen, "GDALDitherRGB2PCT", CE_Failure );
|
||||
VALIDATE_POINTER1( hBlue, "GDALDitherRGB2PCT", CE_Failure );
|
||||
VALIDATE_POINTER1( hTarget, "GDALDitherRGB2PCT", CE_Failure );
|
||||
VALIDATE_POINTER1( hColorTable, "GDALDitherRGB2PCT", CE_Failure );
|
||||
|
||||
int nXSize, nYSize;
|
||||
CPLErr err = CE_None;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Validate parameters. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
nXSize = GDALGetRasterBandXSize( hRed );
|
||||
nYSize = GDALGetRasterBandYSize( hRed );
|
||||
|
||||
if( GDALGetRasterBandXSize( hGreen ) != nXSize
|
||||
|| GDALGetRasterBandYSize( hGreen ) != nYSize
|
||||
|| GDALGetRasterBandXSize( hBlue ) != nXSize
|
||||
|| GDALGetRasterBandYSize( hBlue ) != nYSize )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_IllegalArg,
|
||||
"Green or blue band doesn't match size of red band.\n" );
|
||||
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
if( GDALGetRasterBandXSize( hTarget ) != nXSize
|
||||
|| GDALGetRasterBandYSize( hTarget ) != nYSize )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_IllegalArg,
|
||||
"GDALDitherRGB2PCT(): "
|
||||
"Target band doesn't match size of source bands.\n" );
|
||||
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
if( pfnProgress == NULL )
|
||||
pfnProgress = GDALDummyProgress;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Setup more direct colormap. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int nColors, iColor;
|
||||
#ifdef USE_SSE2
|
||||
int anPCTUnaligned[256+4]; /* 4 for alignment on 16-byte boundary */
|
||||
int* anPCT = ALIGN_INT_ARRAY_ON_16_BYTE(anPCTUnaligned);
|
||||
#else
|
||||
int anPCT[256*4];
|
||||
#endif
|
||||
nColors = GDALGetColorEntryCount( hColorTable );
|
||||
|
||||
if (nColors == 0 )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_IllegalArg,
|
||||
"GDALDitherRGB2PCT(): "
|
||||
"Color table must not be empty.\n" );
|
||||
|
||||
return CE_Failure;
|
||||
}
|
||||
else if (nColors > 256)
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_IllegalArg,
|
||||
"GDALDitherRGB2PCT(): "
|
||||
"Color table cannot have more than 256 entries.\n" );
|
||||
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
for( iColor = 0; iColor < nColors; iColor++ )
|
||||
{
|
||||
GDALColorEntry sEntry;
|
||||
|
||||
GDALGetColorEntryAsRGB( hColorTable, iColor, &sEntry );
|
||||
CAST_PCT(anPCT)[4*iColor+0] = sEntry.c1;
|
||||
CAST_PCT(anPCT)[4*iColor+1] = sEntry.c2;
|
||||
CAST_PCT(anPCT)[4*iColor+2] = sEntry.c3;
|
||||
CAST_PCT(anPCT)[4*iColor+3] = 0;
|
||||
}
|
||||
#ifdef USE_SSE2
|
||||
/* Pad to multiple of 8 colors */
|
||||
int nColorsMod8 = nColors % 8;
|
||||
if( nColorsMod8 )
|
||||
{
|
||||
for( iColor = 0; iColor < 8 - nColorsMod8; iColor ++)
|
||||
{
|
||||
anPCT[nColors+iColor] = anPCT[nColors-1];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Setup various variables. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GByte *pabyRed, *pabyGreen, *pabyBlue, *pabyIndex;
|
||||
GByte *pabyColorMap = NULL;
|
||||
int *panError;
|
||||
int nCLevels = 1 << nBits;
|
||||
ColorIndex* psColorIndexMap = NULL;
|
||||
|
||||
pabyRed = (GByte *) VSIMalloc(nXSize);
|
||||
pabyGreen = (GByte *) VSIMalloc(nXSize);
|
||||
pabyBlue = (GByte *) VSIMalloc(nXSize);
|
||||
|
||||
pabyIndex = (GByte *) VSIMalloc(nXSize);
|
||||
|
||||
panError = (int *) VSICalloc(sizeof(int),(nXSize+2) * 3);
|
||||
|
||||
if (pabyRed == NULL ||
|
||||
pabyGreen == NULL ||
|
||||
pabyBlue == NULL ||
|
||||
pabyIndex == NULL ||
|
||||
panError == NULL)
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_OutOfMemory,
|
||||
"VSIMalloc(): Out of memory in GDALDitherRGB2PCT" );
|
||||
err = CE_Failure;
|
||||
goto end_and_cleanup;
|
||||
}
|
||||
|
||||
if( pasDynamicColorMap == NULL )
|
||||
{
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Build a 24bit to 8 bit color mapping. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
pabyColorMap = (GByte *) VSIMalloc(nCLevels * nCLevels * nCLevels
|
||||
* sizeof(GByte));
|
||||
if( pabyColorMap == NULL )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_OutOfMemory,
|
||||
"VSIMalloc(): Out of memory in GDALDitherRGB2PCT" );
|
||||
err = CE_Failure;
|
||||
goto end_and_cleanup;
|
||||
}
|
||||
|
||||
FindNearestColor( nColors, anPCT, pabyColorMap, nCLevels);
|
||||
}
|
||||
else
|
||||
{
|
||||
pabyColorMap = NULL;
|
||||
if( nBits == 8 && (GIntBig)nXSize * nYSize <= 65536 )
|
||||
{
|
||||
/* If the image is small enough, then the number of colors */
|
||||
/* will be limited and using a hashmap, rather than a full table */
|
||||
/* will be more efficient */
|
||||
psColorIndexMap = (ColorIndex*)pasDynamicColorMap;
|
||||
memset(psColorIndexMap, 0xFF, sizeof(ColorIndex) * PRIME_FOR_65536);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(pasDynamicColorMap, 0xFF, 256 * 256 * 256 * sizeof(GInt16));
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Loop over all scanlines of data to process. */
|
||||
/* ==================================================================== */
|
||||
int iScanline;
|
||||
|
||||
for( iScanline = 0; iScanline < nYSize; iScanline++ )
|
||||
{
|
||||
int nLastRedError, nLastGreenError, nLastBlueError, i;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Report progress */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( !pfnProgress( iScanline / (double) nYSize, NULL, pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User Terminated" );
|
||||
err = CE_Failure;
|
||||
goto end_and_cleanup;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read source data. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GDALRasterIO( hRed, GF_Read, 0, iScanline, nXSize, 1,
|
||||
pabyRed, nXSize, 1, GDT_Byte, 0, 0 );
|
||||
GDALRasterIO( hGreen, GF_Read, 0, iScanline, nXSize, 1,
|
||||
pabyGreen, nXSize, 1, GDT_Byte, 0, 0 );
|
||||
GDALRasterIO( hBlue, GF_Read, 0, iScanline, nXSize, 1,
|
||||
pabyBlue, nXSize, 1, GDT_Byte, 0, 0 );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Apply the error from the previous line to this one. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( bDither )
|
||||
{
|
||||
for( i = 0; i < nXSize; i++ )
|
||||
{
|
||||
pabyRed[i] = (GByte)
|
||||
MAX(0,MIN(255,(pabyRed[i] + panError[i*3+0+3])));
|
||||
pabyGreen[i] = (GByte)
|
||||
MAX(0,MIN(255,(pabyGreen[i] + panError[i*3+1+3])));
|
||||
pabyBlue[i] = (GByte)
|
||||
MAX(0,MIN(255,(pabyBlue[i] + panError[i*3+2+3])));
|
||||
}
|
||||
|
||||
memset( panError, 0, sizeof(int) * (nXSize+2) * 3 );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Figure out the nearest color to the RGB value. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
nLastRedError = 0;
|
||||
nLastGreenError = 0;
|
||||
nLastBlueError = 0;
|
||||
|
||||
for( i = 0; i < nXSize; i++ )
|
||||
{
|
||||
int iIndex, nError, nSixth;
|
||||
int nRedValue, nGreenValue, nBlueValue;
|
||||
|
||||
nRedValue = MAX(0,MIN(255, pabyRed[i] + nLastRedError));
|
||||
nGreenValue = MAX(0,MIN(255, pabyGreen[i] + nLastGreenError));
|
||||
nBlueValue = MAX(0,MIN(255, pabyBlue[i] + nLastBlueError));
|
||||
|
||||
if( psColorIndexMap )
|
||||
{
|
||||
GUInt32 nColorCode = MAKE_COLOR_CODE(nRedValue, nGreenValue, nBlueValue);
|
||||
GUInt32 nIdx = nColorCode % PRIME_FOR_65536;
|
||||
//int nCollisions = 0;
|
||||
//static int nMaxCollisions = 0;
|
||||
while( TRUE )
|
||||
{
|
||||
if( psColorIndexMap[nIdx].nColorCode == nColorCode )
|
||||
{
|
||||
iIndex = psColorIndexMap[nIdx].nIndex;
|
||||
break;
|
||||
}
|
||||
if( (int)psColorIndexMap[nIdx].nColorCode < 0 )
|
||||
{
|
||||
psColorIndexMap[nIdx].nColorCode = nColorCode;
|
||||
iIndex = FindNearestColor( nColors, anPCT,
|
||||
nRedValue, nGreenValue, nBlueValue );
|
||||
psColorIndexMap[nIdx].nIndex = (GByte) iIndex;
|
||||
break;
|
||||
}
|
||||
if( psColorIndexMap[nIdx].nColorCode2 == nColorCode )
|
||||
{
|
||||
iIndex = psColorIndexMap[nIdx].nIndex2;
|
||||
break;
|
||||
}
|
||||
if( (int)psColorIndexMap[nIdx].nColorCode2 < 0 )
|
||||
{
|
||||
psColorIndexMap[nIdx].nColorCode2 = nColorCode;
|
||||
iIndex = FindNearestColor( nColors, anPCT,
|
||||
nRedValue, nGreenValue, nBlueValue );
|
||||
psColorIndexMap[nIdx].nIndex2 = (GByte) iIndex;
|
||||
break;
|
||||
}
|
||||
if( psColorIndexMap[nIdx].nColorCode3 == nColorCode )
|
||||
{
|
||||
iIndex = psColorIndexMap[nIdx].nIndex3;
|
||||
break;
|
||||
}
|
||||
if( (int)psColorIndexMap[nIdx].nColorCode3 < 0 )
|
||||
{
|
||||
psColorIndexMap[nIdx].nColorCode3 = nColorCode;
|
||||
iIndex = FindNearestColor( nColors, anPCT,
|
||||
nRedValue, nGreenValue, nBlueValue );
|
||||
psColorIndexMap[nIdx].nIndex3 = (GByte) iIndex;
|
||||
break;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
//nCollisions ++;
|
||||
nIdx+=257;
|
||||
if( nIdx >= PRIME_FOR_65536 )
|
||||
nIdx -= PRIME_FOR_65536;
|
||||
}
|
||||
while( (int)psColorIndexMap[nIdx].nColorCode >= 0 &&
|
||||
psColorIndexMap[nIdx].nColorCode != nColorCode &&
|
||||
(int)psColorIndexMap[nIdx].nColorCode2 >= 0 &&
|
||||
psColorIndexMap[nIdx].nColorCode2 != nColorCode&&
|
||||
(int)psColorIndexMap[nIdx].nColorCode3 >= 0 &&
|
||||
psColorIndexMap[nIdx].nColorCode3 != nColorCode );
|
||||
/*if( nCollisions > nMaxCollisions )
|
||||
{
|
||||
nMaxCollisions = nCollisions;
|
||||
printf("nCollisions = %d for R=%d,G=%d,B=%d\n",
|
||||
nCollisions, nRedValue, nGreenValue, nBlueValue);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
else if( pasDynamicColorMap == NULL )
|
||||
{
|
||||
int iRed = nRedValue * nCLevels / 256;
|
||||
int iGreen = nGreenValue * nCLevels / 256;
|
||||
int iBlue = nBlueValue * nCLevels / 256;
|
||||
|
||||
iIndex = pabyColorMap[iRed + iGreen * nCLevels
|
||||
+ iBlue * nCLevels * nCLevels];
|
||||
}
|
||||
else
|
||||
{
|
||||
GUInt32 nColorCode = MAKE_COLOR_CODE(nRedValue, nGreenValue, nBlueValue);
|
||||
GInt16* psIndex = &pasDynamicColorMap[nColorCode];
|
||||
if( *psIndex < 0 )
|
||||
iIndex = *psIndex = FindNearestColor( nColors, anPCT,
|
||||
nRedValue,
|
||||
nGreenValue,
|
||||
nBlueValue );
|
||||
else
|
||||
iIndex = *psIndex;
|
||||
}
|
||||
|
||||
pabyIndex[i] = (GByte) iIndex;
|
||||
if( !bDither )
|
||||
continue;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Compute Red error, and carry it on to the next error line. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
nError = nRedValue - CAST_PCT(anPCT)[4*iIndex+0];
|
||||
nSixth = nError / 6;
|
||||
|
||||
panError[i*3 ] += nSixth;
|
||||
panError[i*3+6 ] = nSixth;
|
||||
panError[i*3+3 ] += nError - 5 * nSixth;
|
||||
|
||||
nLastRedError = 2 * nSixth;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Compute Green error, and carry it on to the next error line. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
nError = nGreenValue - CAST_PCT(anPCT)[4*iIndex+1];
|
||||
nSixth = nError / 6;
|
||||
|
||||
panError[i*3 +1] += nSixth;
|
||||
panError[i*3+6+1] = nSixth;
|
||||
panError[i*3+3+1] += nError - 5 * nSixth;
|
||||
|
||||
nLastGreenError = 2 * nSixth;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Compute Blue error, and carry it on to the next error line. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
nError = nBlueValue - CAST_PCT(anPCT)[4*iIndex+2];
|
||||
nSixth = nError / 6;
|
||||
|
||||
panError[i*3 +2] += nSixth;
|
||||
panError[i*3+6+2] = nSixth;
|
||||
panError[i*3+3+2] += nError - 5 * nSixth;
|
||||
|
||||
nLastBlueError = 2 * nSixth;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Write results. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GDALRasterIO( hTarget, GF_Write, 0, iScanline, nXSize, 1,
|
||||
pabyIndex, nXSize, 1, GDT_Byte, 0, 0 );
|
||||
}
|
||||
|
||||
pfnProgress( 1.0, NULL, pProgressArg );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Cleanup */
|
||||
/* -------------------------------------------------------------------- */
|
||||
end_and_cleanup:
|
||||
CPLFree( pabyRed );
|
||||
CPLFree( pabyGreen );
|
||||
CPLFree( pabyBlue );
|
||||
CPLFree( pabyIndex );
|
||||
CPLFree( panError );
|
||||
CPLFree( pabyColorMap );
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int FindNearestColor( int nColors, int *panPCT,
|
||||
int nRedValue, int nGreenValue, int nBlueValue )
|
||||
|
||||
{
|
||||
#ifdef USE_SSE2
|
||||
int iColor;
|
||||
|
||||
int nBestDist = 768, nBestIndex = 0;
|
||||
|
||||
int anDistanceUnaligned[16+4]; /* 4 for alignment on 16-byte boundary */
|
||||
int* anDistance = ALIGN_INT_ARRAY_ON_16_BYTE(anDistanceUnaligned);
|
||||
|
||||
const __m128i ff = _mm_set1_epi32(0xFFFFFFFF);
|
||||
const __m128i mask_low = _mm_srli_epi64(ff, 32);
|
||||
const __m128i mask_high = _mm_slli_epi64(ff, 32);
|
||||
|
||||
unsigned int nColorVal = MAKE_COLOR_CODE(nRedValue, nGreenValue, nBlueValue);
|
||||
const __m128i thisColor = _mm_set1_epi32(nColorVal);
|
||||
const __m128i thisColor_low = _mm_srli_epi64(thisColor, 32);
|
||||
const __m128i thisColor_high = _mm_slli_epi64(thisColor, 32);
|
||||
|
||||
for( iColor = 0; iColor < nColors; iColor+=8 )
|
||||
{
|
||||
__m128i pctColor = _mm_load_si128((__m128i*)&panPCT[iColor]);
|
||||
__m128i pctColor2 = _mm_load_si128((__m128i*)&panPCT[iColor+4]);
|
||||
|
||||
_mm_store_si128((__m128i*)anDistance,
|
||||
_mm_sad_epu8(_mm_and_si128(pctColor,mask_low),thisColor_low));
|
||||
_mm_store_si128((__m128i*)(anDistance+4),
|
||||
_mm_sad_epu8(_mm_and_si128(pctColor,mask_high),thisColor_high));
|
||||
_mm_store_si128((__m128i*)(anDistance+8),
|
||||
_mm_sad_epu8(_mm_and_si128(pctColor2,mask_low),thisColor_low));
|
||||
_mm_store_si128((__m128i*)(anDistance+12),
|
||||
_mm_sad_epu8(_mm_and_si128(pctColor2,mask_high),thisColor_high));
|
||||
|
||||
if( anDistance[0] < nBestDist )
|
||||
{
|
||||
nBestIndex = iColor;
|
||||
nBestDist = anDistance[0];
|
||||
}
|
||||
if( anDistance[4] < nBestDist )
|
||||
{
|
||||
nBestIndex = iColor+1;
|
||||
nBestDist = anDistance[4];
|
||||
}
|
||||
if( anDistance[2] < nBestDist )
|
||||
{
|
||||
nBestIndex = iColor+2;
|
||||
nBestDist = anDistance[2];
|
||||
}
|
||||
if( anDistance[6] < nBestDist )
|
||||
{
|
||||
nBestIndex = iColor+3;
|
||||
nBestDist = anDistance[6];
|
||||
}
|
||||
if( anDistance[8+0] < nBestDist )
|
||||
{
|
||||
nBestIndex = iColor+4;
|
||||
nBestDist = anDistance[8+0];
|
||||
}
|
||||
if( anDistance[8+4] < nBestDist )
|
||||
{
|
||||
nBestIndex = iColor+4+1;
|
||||
nBestDist = anDistance[8+4];
|
||||
}
|
||||
if( anDistance[8+2] < nBestDist )
|
||||
{
|
||||
nBestIndex = iColor+4+2;
|
||||
nBestDist = anDistance[8+2];
|
||||
}
|
||||
if( anDistance[8+6] < nBestDist )
|
||||
{
|
||||
nBestIndex = iColor+4+3;
|
||||
nBestDist = anDistance[8+6];
|
||||
}
|
||||
}
|
||||
return nBestIndex;
|
||||
#else
|
||||
int iColor;
|
||||
|
||||
int nBestDist = 768, nBestIndex = 0;
|
||||
|
||||
for( iColor = 0; iColor < nColors; iColor++ )
|
||||
{
|
||||
int nThisDist;
|
||||
|
||||
nThisDist = ABS(nRedValue - panPCT[4*iColor+0])
|
||||
+ ABS(nGreenValue - panPCT[4*iColor+1])
|
||||
+ ABS(nBlueValue - panPCT[4*iColor+2]);
|
||||
|
||||
if( nThisDist < nBestDist )
|
||||
{
|
||||
nBestIndex = iColor;
|
||||
nBestDist = nThisDist;
|
||||
}
|
||||
}
|
||||
return nBestIndex;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* FindNearestColor() */
|
||||
/* */
|
||||
/* Finear near PCT color for any RGB color. */
|
||||
/************************************************************************/
|
||||
|
||||
static void FindNearestColor( int nColors, int *panPCT, GByte *pabyColorMap,
|
||||
int nCLevels )
|
||||
|
||||
{
|
||||
int iBlue, iGreen, iRed;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Loop over all the cells in the high density cube. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( iBlue = 0; iBlue < nCLevels; iBlue++ )
|
||||
{
|
||||
for( iGreen = 0; iGreen < nCLevels; iGreen++ )
|
||||
{
|
||||
for( iRed = 0; iRed < nCLevels; iRed++ )
|
||||
{
|
||||
int nRedValue, nGreenValue, nBlueValue;
|
||||
|
||||
nRedValue = (iRed * 255) / (nCLevels-1);
|
||||
nGreenValue = (iGreen * 255) / (nCLevels-1);
|
||||
nBlueValue = (iBlue * 255) / (nCLevels-1);
|
||||
|
||||
int nBestIndex = FindNearestColor( nColors, panPCT,
|
||||
nRedValue, nGreenValue, nBlueValue );
|
||||
pabyColorMap[iRed + iGreen*nCLevels
|
||||
+ iBlue*nCLevels*nCLevels] = (GByte)nBestIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1280
bazaar/plugin/gdal/alg/gdalgeoloc.cpp
Normal file
1280
bazaar/plugin/gdal/alg/gdalgeoloc.cpp
Normal file
File diff suppressed because it is too large
Load diff
2000
bazaar/plugin/gdal/alg/gdalgrid.cpp
Normal file
2000
bazaar/plugin/gdal/alg/gdalgrid.cpp
Normal file
File diff suppressed because it is too large
Load diff
122
bazaar/plugin/gdal/alg/gdalgrid.h
Normal file
122
bazaar/plugin/gdal/alg/gdalgrid.h
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdalgrid.h 27044 2014-03-16 23:41:27Z rouault $
|
||||
*
|
||||
* Project: GDAL Gridding API.
|
||||
* Purpose: Prototypes, and definitions for of GDAL scattered data gridder.
|
||||
* Author: Andrey Kiselev, dron@ak4719.spb.edu
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2007, Andrey Kiselev <dron@ak4719.spb.edu>
|
||||
* Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef GDALGRID_H_INCLUDED
|
||||
#define GDALGRID_H_INCLUDED
|
||||
|
||||
/**
|
||||
* \file gdalgrid.h
|
||||
*
|
||||
* GDAL gridder related entry points and definitions.
|
||||
*/
|
||||
|
||||
#include "gdal_alg.h"
|
||||
|
||||
/*
|
||||
* GridCreate Algorithm names
|
||||
*/
|
||||
|
||||
static const char szAlgNameInvDist[] = "invdist";
|
||||
static const char szAlgNameAverage[] = "average";
|
||||
static const char szAlgNameNearest[] = "nearest";
|
||||
static const char szAlgNameMinimum[] = "minimum";
|
||||
static const char szAlgNameMaximum[] = "maximum";
|
||||
static const char szAlgNameRange[] = "range";
|
||||
static const char szAlgNameCount[] = "count";
|
||||
static const char szAlgNameAverageDistance[] = "average_distance";
|
||||
static const char szAlgNameAverageDistancePts[] = "average_distance_pts";
|
||||
|
||||
CPL_C_START
|
||||
|
||||
typedef CPLErr (*GDALGridFunction)( const void *, GUInt32,
|
||||
const double *, const double *,
|
||||
const double *,
|
||||
double, double, double *,
|
||||
void* );
|
||||
CPLErr
|
||||
GDALGridInverseDistanceToAPower( const void *, GUInt32,
|
||||
const double *, const double *,
|
||||
const double *,
|
||||
double, double, double *,
|
||||
void* );
|
||||
CPLErr
|
||||
GDALGridInverseDistanceToAPowerNoSearch( const void *, GUInt32,
|
||||
const double *, const double *,
|
||||
const double *,
|
||||
double, double, double *,
|
||||
void* );
|
||||
CPLErr
|
||||
GDALGridMovingAverage( const void *, GUInt32,
|
||||
const double *, const double *, const double *,
|
||||
double, double, double *,
|
||||
void* );
|
||||
CPLErr
|
||||
GDALGridNearestNeighbor( const void *, GUInt32,
|
||||
const double *, const double *, const double *,
|
||||
double, double, double *,
|
||||
void* );
|
||||
CPLErr
|
||||
GDALGridDataMetricMinimum( const void *, GUInt32,
|
||||
const double *, const double *, const double *,
|
||||
double, double, double *,
|
||||
void* );
|
||||
CPLErr
|
||||
GDALGridDataMetricMaximum( const void *, GUInt32,
|
||||
const double *, const double *, const double *,
|
||||
double, double, double *,
|
||||
void* );
|
||||
CPLErr
|
||||
GDALGridDataMetricRange( const void *, GUInt32,
|
||||
const double *, const double *, const double *,
|
||||
double, double, double *,
|
||||
void* );
|
||||
CPLErr
|
||||
GDALGridDataMetricCount( const void *, GUInt32,
|
||||
const double *, const double *, const double *,
|
||||
double, double, double *,
|
||||
void* );
|
||||
CPLErr
|
||||
GDALGridDataMetricAverageDistance( const void *, GUInt32,
|
||||
const double *, const double *,
|
||||
const double *, double, double, double *,
|
||||
void* );
|
||||
CPLErr
|
||||
GDALGridDataMetricAverageDistancePts( const void *, GUInt32,
|
||||
const double *, const double *,
|
||||
const double *, double, double,
|
||||
double *,
|
||||
void* );
|
||||
CPLErr CPL_DLL
|
||||
ParseAlgorithmAndOptions( const char *,
|
||||
GDALGridAlgorithm *,
|
||||
void ** );
|
||||
CPL_C_END
|
||||
|
||||
#endif /* GDALGRID_H_INCLUDED */
|
||||
99
bazaar/plugin/gdal/alg/gdalgrid_priv.h
Normal file
99
bazaar/plugin/gdal/alg/gdalgrid_priv.h
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdalgrid_priv.h 29314 2015-06-05 20:21:11Z rouault $
|
||||
*
|
||||
* Project: GDAL Gridding API.
|
||||
* Purpose: Prototypes, and definitions for of GDAL scattered data gridder.
|
||||
* Author: Even Rouault, <even dot rouault at mines dash paris dot org>
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "cpl_error.h"
|
||||
#include "cpl_quad_tree.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const double* padfX;
|
||||
const double* padfY;
|
||||
} GDALGridXYArrays;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GDALGridXYArrays* psXYArrays;
|
||||
int i;
|
||||
} GDALGridPoint;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CPLQuadTree* hQuadTree;
|
||||
double dfInitialSearchRadius;
|
||||
const float *pafX;
|
||||
const float *pafY;
|
||||
const float *pafZ;
|
||||
} GDALGridExtraParameters;
|
||||
|
||||
#ifdef HAVE_SSE_AT_COMPILE_TIME
|
||||
int CPLHaveRuntimeSSE();
|
||||
|
||||
CPLErr
|
||||
GDALGridInverseDistanceToAPower2NoSmoothingNoSearchSSE(
|
||||
const void *poOptions,
|
||||
GUInt32 nPoints,
|
||||
const double *unused_padfX,
|
||||
const double *unused_padfY,
|
||||
const double *unused_padfZ,
|
||||
double dfXPoint, double dfYPoint,
|
||||
double *pdfValue,
|
||||
void* hExtraParamsIn );
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_AVX_AT_COMPILE_TIME
|
||||
int CPLHaveRuntimeAVX();
|
||||
|
||||
CPLErr GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX(
|
||||
const void *poOptions,
|
||||
GUInt32 nPoints,
|
||||
const double *unused_padfX,
|
||||
const double *unused_padfY,
|
||||
const double *unused_padfZ,
|
||||
double dfXPoint, double dfYPoint,
|
||||
double *pdfValue,
|
||||
void* hExtraParamsIn );
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__x86_64)
|
||||
#define GCC_CPUID(level, a, b, c, d) \
|
||||
__asm__ ("xchgq %%rbx, %q1\n" \
|
||||
"cpuid\n" \
|
||||
"xchgq %%rbx, %q1" \
|
||||
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
|
||||
: "0" (level))
|
||||
#else
|
||||
#define GCC_CPUID(level, a, b, c, d) \
|
||||
__asm__ ("xchgl %%ebx, %1\n" \
|
||||
"cpuid\n" \
|
||||
"xchgl %%ebx, %1" \
|
||||
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
|
||||
: "0" (level))
|
||||
#endif
|
||||
#endif
|
||||
225
bazaar/plugin/gdal/alg/gdalgridavx.cpp
Normal file
225
bazaar/plugin/gdal/alg/gdalgridavx.cpp
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdalgridavx.cpp 27745 2014-09-27 16:38:57Z goatbar $
|
||||
*
|
||||
* Project: GDAL Gridding API.
|
||||
* Purpose: Implementation of GDAL scattered data gridder.
|
||||
* Author: Even Rouault, <even dot rouault at mines dash paris dot org>
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdalgrid.h"
|
||||
#include "gdalgrid_priv.h"
|
||||
|
||||
#ifdef HAVE_AVX_AT_COMPILE_TIME
|
||||
#include <immintrin.h>
|
||||
|
||||
CPL_CVSID("$Id: gdalgridavx.cpp 27745 2014-09-27 16:38:57Z goatbar $");
|
||||
|
||||
/************************************************************************/
|
||||
/* CPLHaveRuntimeAVX() */
|
||||
/************************************************************************/
|
||||
|
||||
#define CPUID_OSXSAVE_ECX_BIT 27
|
||||
#define CPUID_AVX_ECX_BIT 28
|
||||
|
||||
#define BIT_XMM_STATE (1 << 1)
|
||||
#define BIT_YMM_STATE (2 << 1)
|
||||
|
||||
int CPLHaveRuntimeAVX()
|
||||
{
|
||||
int cpuinfo[4] = {0,0,0,0};
|
||||
GCC_CPUID(1, cpuinfo[0], cpuinfo[1], cpuinfo[2], cpuinfo[3]);
|
||||
|
||||
/* Check OSXSAVE feature */
|
||||
if( (cpuinfo[2] & (1 << CPUID_OSXSAVE_ECX_BIT)) == 0 )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check AVX feature */
|
||||
if( (cpuinfo[2] & (1 << CPUID_AVX_ECX_BIT)) == 0 )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Issue XGETBV and check the XMM and YMM state bit */
|
||||
unsigned int nXCRLow;
|
||||
unsigned int nXCRHigh;
|
||||
__asm__ ("xgetbv" : "=a" (nXCRLow), "=d" (nXCRHigh) : "c" (0));
|
||||
if( (nXCRLow & ( BIT_XMM_STATE | BIT_YMM_STATE )) !=
|
||||
( BIT_XMM_STATE | BIT_YMM_STATE ) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX() */
|
||||
/************************************************************************/
|
||||
|
||||
#define GDAL_mm256_load1_ps(x) _mm256_set_ps(x, x, x, x, x, x, x, x)
|
||||
|
||||
CPLErr
|
||||
GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX(
|
||||
const void *poOptions,
|
||||
GUInt32 nPoints,
|
||||
CPL_UNUSED const double *unused_padfX,
|
||||
CPL_UNUSED const double *unused_padfY,
|
||||
CPL_UNUSED const double *unused_padfZ,
|
||||
double dfXPoint, double dfYPoint,
|
||||
double *pdfValue,
|
||||
void* hExtraParamsIn )
|
||||
{
|
||||
size_t i = 0;
|
||||
GDALGridExtraParameters* psExtraParams = (GDALGridExtraParameters*) hExtraParamsIn;
|
||||
const float* pafX = psExtraParams->pafX;
|
||||
const float* pafY = psExtraParams->pafY;
|
||||
const float* pafZ = psExtraParams->pafZ;
|
||||
|
||||
const float fEpsilon = 0.0000000000001f;
|
||||
const float fXPoint = (float)dfXPoint;
|
||||
const float fYPoint = (float)dfYPoint;
|
||||
const __m256 ymm_small = GDAL_mm256_load1_ps(fEpsilon);
|
||||
const __m256 ymm_x = GDAL_mm256_load1_ps(fXPoint);
|
||||
const __m256 ymm_y = GDAL_mm256_load1_ps(fYPoint);
|
||||
__m256 ymm_nominator = _mm256_setzero_ps();
|
||||
__m256 ymm_denominator = _mm256_setzero_ps();
|
||||
int mask = 0;
|
||||
|
||||
#undef LOOP_SIZE
|
||||
#if defined(__x86_64) || defined(_M_X64)
|
||||
/* This would also work in 32bit mode, but there are only 8 XMM registers */
|
||||
/* whereas we have 16 for 64bit */
|
||||
#define LOOP_SIZE 16
|
||||
size_t nPointsRound = (nPoints / LOOP_SIZE) * LOOP_SIZE;
|
||||
for ( i = 0; i < nPointsRound; i += LOOP_SIZE )
|
||||
{
|
||||
__m256 ymm_rx = _mm256_sub_ps(_mm256_load_ps(pafX + i), ymm_x); /* rx = pafX[i] - fXPoint */
|
||||
__m256 ymm_rx_8 = _mm256_sub_ps(_mm256_load_ps(pafX + i + 8), ymm_x);
|
||||
__m256 ymm_ry = _mm256_sub_ps(_mm256_load_ps(pafY + i), ymm_y); /* ry = pafY[i] - fYPoint */
|
||||
__m256 ymm_ry_8 = _mm256_sub_ps(_mm256_load_ps(pafY + i + 8), ymm_y);
|
||||
__m256 ymm_r2 = _mm256_add_ps(_mm256_mul_ps(ymm_rx, ymm_rx), /* r2 = rx * rx + ry * ry */
|
||||
_mm256_mul_ps(ymm_ry, ymm_ry));
|
||||
__m256 ymm_r2_8 = _mm256_add_ps(_mm256_mul_ps(ymm_rx_8, ymm_rx_8),
|
||||
_mm256_mul_ps(ymm_ry_8, ymm_ry_8));
|
||||
__m256 ymm_invr2 = _mm256_rcp_ps(ymm_r2); /* invr2 = 1.0f / r2 */
|
||||
__m256 ymm_invr2_8 = _mm256_rcp_ps(ymm_r2_8);
|
||||
ymm_nominator = _mm256_add_ps(ymm_nominator, /* nominator += invr2 * pafZ[i] */
|
||||
_mm256_mul_ps(ymm_invr2, _mm256_load_ps(pafZ + i)));
|
||||
ymm_nominator = _mm256_add_ps(ymm_nominator,
|
||||
_mm256_mul_ps(ymm_invr2_8, _mm256_load_ps(pafZ + i + 8)));
|
||||
ymm_denominator = _mm256_add_ps(ymm_denominator, ymm_invr2); /* denominator += invr2 */
|
||||
ymm_denominator = _mm256_add_ps(ymm_denominator, ymm_invr2_8);
|
||||
mask = _mm256_movemask_ps(_mm256_cmp_ps(ymm_r2, ymm_small, _CMP_LT_OS)) | /* if( r2 < fEpsilon) */
|
||||
(_mm256_movemask_ps(_mm256_cmp_ps(ymm_r2_8, ymm_small, _CMP_LT_OS)) << 8);
|
||||
if( mask )
|
||||
break;
|
||||
}
|
||||
#else
|
||||
#define LOOP_SIZE 8
|
||||
size_t nPointsRound = (nPoints / LOOP_SIZE) * LOOP_SIZE;
|
||||
for ( i = 0; i < nPointsRound; i += LOOP_SIZE )
|
||||
{
|
||||
__m256 ymm_rx = _mm256_sub_ps(_mm256_load_ps((float*)pafX + i), ymm_x); /* rx = pafX[i] - fXPoint */
|
||||
__m256 ymm_ry = _mm256_sub_ps(_mm256_load_ps((float*)pafY + i), ymm_y); /* ry = pafY[i] - fYPoint */
|
||||
__m256 ymm_r2 = _mm256_add_ps(_mm256_mul_ps(ymm_rx, ymm_rx), /* r2 = rx * rx + ry * ry */
|
||||
_mm256_mul_ps(ymm_ry, ymm_ry));
|
||||
__m256 ymm_invr2 = _mm256_rcp_ps(ymm_r2); /* invr2 = 1.0f / r2 */
|
||||
ymm_nominator = _mm256_add_ps(ymm_nominator, /* nominator += invr2 * pafZ[i] */
|
||||
_mm256_mul_ps(ymm_invr2, _mm256_load_ps((float*)pafZ + i)));
|
||||
ymm_denominator = _mm256_add_ps(ymm_denominator, ymm_invr2); /* denominator += invr2 */
|
||||
mask = _mm256_movemask_ps(_mm256_cmp_ps(ymm_r2, ymm_small, _CMP_LT_OS)); /* if( r2 < fEpsilon) */
|
||||
if( mask )
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Find which i triggered r2 < fEpsilon */
|
||||
if( mask )
|
||||
{
|
||||
for(int j = 0; j < LOOP_SIZE; j++ )
|
||||
{
|
||||
if( mask & (1 << j) )
|
||||
{
|
||||
(*pdfValue) = (pafZ)[i + j];
|
||||
return CE_None;
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef LOOP_SIZE
|
||||
|
||||
/* Get back nominator and denominator values for YMM registers */
|
||||
float afNominator[8], afDenominator[8];
|
||||
_mm256_storeu_ps(afNominator, ymm_nominator);
|
||||
_mm256_storeu_ps(afDenominator, ymm_denominator);
|
||||
|
||||
float fNominator = afNominator[0] + afNominator[1] +
|
||||
afNominator[2] + afNominator[3] +
|
||||
afNominator[4] + afNominator[5] +
|
||||
afNominator[6] + afNominator[7];
|
||||
float fDenominator = afDenominator[0] + afDenominator[1] +
|
||||
afDenominator[2] + afDenominator[3] +
|
||||
afDenominator[4] + afDenominator[5] +
|
||||
afDenominator[6] + afDenominator[7];
|
||||
|
||||
/* Do the few remaining loop iterations */
|
||||
for ( ; i < nPoints; i++ )
|
||||
{
|
||||
const float fRX = pafX[i] - fXPoint;
|
||||
const float fRY = pafY[i] - fYPoint;
|
||||
const float fR2 =
|
||||
fRX * fRX + fRY * fRY;
|
||||
|
||||
// If the test point is close to the grid node, use the point
|
||||
// value directly as a node value to avoid singularity.
|
||||
if ( fR2 < 0.0000000000001 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float fInvR2 = 1.0f / fR2;
|
||||
fNominator += fInvR2 * pafZ[i];
|
||||
fDenominator += fInvR2;
|
||||
}
|
||||
}
|
||||
|
||||
if( i != nPoints )
|
||||
{
|
||||
(*pdfValue) = pafZ[i];
|
||||
}
|
||||
else
|
||||
if ( fDenominator == 0.0 )
|
||||
{
|
||||
(*pdfValue) =
|
||||
((GDALGridInverseDistanceToAPowerOptions*)poOptions)->dfNoDataValue;
|
||||
}
|
||||
else
|
||||
(*pdfValue) = fNominator / fDenominator;
|
||||
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
#endif
|
||||
241
bazaar/plugin/gdal/alg/gdalgridsse.cpp
Normal file
241
bazaar/plugin/gdal/alg/gdalgridsse.cpp
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdalgridsse.cpp 28033 2014-11-30 16:37:24Z rouault $
|
||||
*
|
||||
* Project: GDAL Gridding API.
|
||||
* Purpose: Implementation of GDAL scattered data gridder.
|
||||
* Author: Even Rouault, <even dot rouault at mines dash paris dot org>
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdalgrid.h"
|
||||
#include "gdalgrid_priv.h"
|
||||
|
||||
#ifdef HAVE_SSE_AT_COMPILE_TIME
|
||||
#include <xmmintrin.h>
|
||||
|
||||
CPL_CVSID("$Id: gdalgridsse.cpp 28033 2014-11-30 16:37:24Z rouault $");
|
||||
|
||||
/************************************************************************/
|
||||
/* CPLHaveRuntimeSSE() */
|
||||
/************************************************************************/
|
||||
|
||||
#define CPUID_SSE_EDX_BIT 25
|
||||
|
||||
#if (defined(_M_X64) || defined(__x86_64))
|
||||
|
||||
int CPLHaveRuntimeSSE()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#elif defined(__GNUC__) && defined(__i386__)
|
||||
|
||||
int CPLHaveRuntimeSSE()
|
||||
{
|
||||
int cpuinfo[4] = {0,0,0,0};
|
||||
GCC_CPUID(1, cpuinfo[0], cpuinfo[1], cpuinfo[2], cpuinfo[3]);
|
||||
return (cpuinfo[3] & (1 << CPUID_SSE_EDX_BIT)) != 0;
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER) && defined(_M_IX86)
|
||||
|
||||
#if _MSC_VER <= 1310
|
||||
static void inline __cpuid(int cpuinfo[4], int level)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push ebx
|
||||
push esi
|
||||
|
||||
mov esi,cpuinfo
|
||||
mov eax,level
|
||||
cpuid
|
||||
mov dword ptr [esi], eax
|
||||
mov dword ptr [esi+4],ebx
|
||||
mov dword ptr [esi+8],ecx
|
||||
mov dword ptr [esi+0Ch],edx
|
||||
|
||||
pop esi
|
||||
pop ebx
|
||||
}
|
||||
}
|
||||
#else
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
int CPLHaveRuntimeSSE()
|
||||
{
|
||||
int cpuinfo[4] = {0,0,0,0};
|
||||
__cpuid(cpuinfo, 1);
|
||||
return (cpuinfo[3] & (1 << CPUID_SSE_EDX_BIT)) != 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int CPLHaveRuntimeSSE()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALGridInverseDistanceToAPower2NoSmoothingNoSearchSSE() */
|
||||
/************************************************************************/
|
||||
|
||||
CPLErr
|
||||
GDALGridInverseDistanceToAPower2NoSmoothingNoSearchSSE(
|
||||
const void *poOptions,
|
||||
GUInt32 nPoints,
|
||||
CPL_UNUSED const double *unused_padfX,
|
||||
CPL_UNUSED const double *unused_padfY,
|
||||
CPL_UNUSED const double *unused_padfZ,
|
||||
double dfXPoint, double dfYPoint,
|
||||
double *pdfValue,
|
||||
void* hExtraParamsIn )
|
||||
{
|
||||
size_t i = 0;
|
||||
GDALGridExtraParameters* psExtraParams = (GDALGridExtraParameters*) hExtraParamsIn;
|
||||
const float* pafX = psExtraParams->pafX;
|
||||
const float* pafY = psExtraParams->pafY;
|
||||
const float* pafZ = psExtraParams->pafZ;
|
||||
|
||||
const float fEpsilon = 0.0000000000001f;
|
||||
const float fXPoint = (float)dfXPoint;
|
||||
const float fYPoint = (float)dfYPoint;
|
||||
const __m128 xmm_small = _mm_load1_ps((float*)&fEpsilon);
|
||||
const __m128 xmm_x = _mm_load1_ps((float*)&fXPoint);
|
||||
const __m128 xmm_y = _mm_load1_ps((float*)&fYPoint);
|
||||
__m128 xmm_nominator = _mm_setzero_ps();
|
||||
__m128 xmm_denominator = _mm_setzero_ps();
|
||||
int mask = 0;
|
||||
|
||||
#if defined(__x86_64) || defined(_M_X64)
|
||||
/* This would also work in 32bit mode, but there are only 8 XMM registers */
|
||||
/* whereas we have 16 for 64bit */
|
||||
#define LOOP_SIZE 8
|
||||
size_t nPointsRound = (nPoints / LOOP_SIZE) * LOOP_SIZE;
|
||||
for ( i = 0; i < nPointsRound; i += LOOP_SIZE )
|
||||
{
|
||||
__m128 xmm_rx = _mm_sub_ps(_mm_load_ps(pafX + i), xmm_x); /* rx = pafX[i] - fXPoint */
|
||||
__m128 xmm_rx_4 = _mm_sub_ps(_mm_load_ps(pafX + i + 4), xmm_x);
|
||||
__m128 xmm_ry = _mm_sub_ps(_mm_load_ps(pafY + i), xmm_y); /* ry = pafY[i] - fYPoint */
|
||||
__m128 xmm_ry_4 = _mm_sub_ps(_mm_load_ps(pafY + i + 4), xmm_y);
|
||||
__m128 xmm_r2 = _mm_add_ps(_mm_mul_ps(xmm_rx, xmm_rx), /* r2 = rx * rx + ry * ry */
|
||||
_mm_mul_ps(xmm_ry, xmm_ry));
|
||||
__m128 xmm_r2_4 = _mm_add_ps(_mm_mul_ps(xmm_rx_4, xmm_rx_4),
|
||||
_mm_mul_ps(xmm_ry_4, xmm_ry_4));
|
||||
__m128 xmm_invr2 = _mm_rcp_ps(xmm_r2); /* invr2 = 1.0f / r2 */
|
||||
__m128 xmm_invr2_4 = _mm_rcp_ps(xmm_r2_4);
|
||||
xmm_nominator = _mm_add_ps(xmm_nominator, /* nominator += invr2 * pafZ[i] */
|
||||
_mm_mul_ps(xmm_invr2, _mm_load_ps(pafZ + i)));
|
||||
xmm_nominator = _mm_add_ps(xmm_nominator,
|
||||
_mm_mul_ps(xmm_invr2_4, _mm_load_ps(pafZ + i + 4)));
|
||||
xmm_denominator = _mm_add_ps(xmm_denominator, xmm_invr2); /* denominator += invr2 */
|
||||
xmm_denominator = _mm_add_ps(xmm_denominator, xmm_invr2_4);
|
||||
mask = _mm_movemask_ps(_mm_cmplt_ps(xmm_r2, xmm_small)) | /* if( r2 < fEpsilon) */
|
||||
(_mm_movemask_ps(_mm_cmplt_ps(xmm_r2_4, xmm_small)) << 4);
|
||||
if( mask )
|
||||
break;
|
||||
}
|
||||
#else
|
||||
#define LOOP_SIZE 4
|
||||
size_t nPointsRound = (nPoints / LOOP_SIZE) * LOOP_SIZE;
|
||||
for ( i = 0; i < nPointsRound; i += LOOP_SIZE )
|
||||
{
|
||||
__m128 xmm_rx = _mm_sub_ps(_mm_load_ps((float*)pafX + i), xmm_x); /* rx = pafX[i] - fXPoint */
|
||||
__m128 xmm_ry = _mm_sub_ps(_mm_load_ps((float*)pafY + i), xmm_y); /* ry = pafY[i] - fYPoint */
|
||||
__m128 xmm_r2 = _mm_add_ps(_mm_mul_ps(xmm_rx, xmm_rx), /* r2 = rx * rx + ry * ry */
|
||||
_mm_mul_ps(xmm_ry, xmm_ry));
|
||||
__m128 xmm_invr2 = _mm_rcp_ps(xmm_r2); /* invr2 = 1.0f / r2 */
|
||||
xmm_nominator = _mm_add_ps(xmm_nominator, /* nominator += invr2 * pafZ[i] */
|
||||
_mm_mul_ps(xmm_invr2, _mm_load_ps((float*)pafZ + i)));
|
||||
xmm_denominator = _mm_add_ps(xmm_denominator, xmm_invr2); /* denominator += invr2 */
|
||||
mask = _mm_movemask_ps(_mm_cmplt_ps(xmm_r2, xmm_small)); /* if( r2 < fEpsilon) */
|
||||
if( mask )
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Find which i triggered r2 < fEpsilon */
|
||||
if( mask )
|
||||
{
|
||||
for(int j = 0; j < LOOP_SIZE; j++ )
|
||||
{
|
||||
if( mask & (1 << j) )
|
||||
{
|
||||
(*pdfValue) = (pafZ)[i + j];
|
||||
return CE_None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get back nominator and denominator values for XMM registers */
|
||||
float afNominator[4], afDenominator[4];
|
||||
_mm_storeu_ps(afNominator, xmm_nominator);
|
||||
_mm_storeu_ps(afDenominator, xmm_denominator);
|
||||
|
||||
float fNominator = afNominator[0] + afNominator[1] +
|
||||
afNominator[2] + afNominator[3];
|
||||
float fDenominator = afDenominator[0] + afDenominator[1] +
|
||||
afDenominator[2] + afDenominator[3];
|
||||
|
||||
/* Do the few remaining loop iterations */
|
||||
for ( ; i < nPoints; i++ )
|
||||
{
|
||||
const float fRX = pafX[i] - fXPoint;
|
||||
const float fRY = pafY[i] - fYPoint;
|
||||
const float fR2 =
|
||||
fRX * fRX + fRY * fRY;
|
||||
|
||||
// If the test point is close to the grid node, use the point
|
||||
// value directly as a node value to avoid singularity.
|
||||
if ( fR2 < 0.0000000000001 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float fInvR2 = 1.0f / fR2;
|
||||
fNominator += fInvR2 * pafZ[i];
|
||||
fDenominator += fInvR2;
|
||||
}
|
||||
}
|
||||
|
||||
if( i != nPoints )
|
||||
{
|
||||
(*pdfValue) = pafZ[i];
|
||||
}
|
||||
else
|
||||
if ( fDenominator == 0.0 )
|
||||
{
|
||||
(*pdfValue) =
|
||||
((GDALGridInverseDistanceToAPowerOptions*)poOptions)->dfNoDataValue;
|
||||
}
|
||||
else
|
||||
(*pdfValue) = fNominator / fDenominator;
|
||||
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_SSE_AT_COMPILE_TIME */
|
||||
299
bazaar/plugin/gdal/alg/gdalmatching.cpp
Normal file
299
bazaar/plugin/gdal/alg/gdalmatching.cpp
Normal file
|
|
@ -0,0 +1,299 @@
|
|||
/******************************************************************************
|
||||
* $Id$
|
||||
*
|
||||
* Project: GDAL
|
||||
* Purpose: GDAL Wrapper for image matching via corellation algorithm.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
* Author: Andrew Migal, migal.drew@gmail.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2012, Frank Warmerdam
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_alg.h"
|
||||
#include "gdal_simplesurf.h"
|
||||
|
||||
CPL_CVSID("$Id");
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @author Andrew Migal migal.drew@gmail.com
|
||||
* @brief Algorithms for searching corresponding points on images.
|
||||
* @details This implementation is based on an simplified version
|
||||
* of SURF algorithm (Speeded Up Robust Features).
|
||||
* Provides capability for detection feature points
|
||||
* and finding equal points on different images.
|
||||
* As original, this realization is scale invariant, but sensitive to rotation.
|
||||
* Images should have similar rotation angles (maximum difference is up to 10-15 degrees),
|
||||
* otherwise algorithm produces incorrect and very unstable results.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Detect feature points on provided image. Please carefully read documentation below.
|
||||
*
|
||||
* @param poDataset Image on which feature points will be detected
|
||||
* @param panBands Array of 3 raster bands numbers, for Red, Green, Blue bands (in that order)
|
||||
* @param nOctaveStart Number of bottom octave. Octave numbers starts from one.
|
||||
* This value directly and strongly affects to amount of recognized points
|
||||
* @param nOctaveEnd Number of top octave. Should be equal or greater than octaveStart
|
||||
* @param dfThreshold Value from 0 to 1. Threshold for feature point recognition.
|
||||
* Number of detected points is larger if threshold is lower
|
||||
*
|
||||
* @see GDALFeaturePoint, GDALSimpleSURF class for detailes.
|
||||
*
|
||||
* @note Every octave finds points in specific size. For small images
|
||||
* use small octave numbers, for high resolution - large.
|
||||
* For 1024x1024 images it's normal to use any octave numbers from range 1-6.
|
||||
* (for example, octave start - 1, octave end - 3, or octave start - 2, octave end - 2.)
|
||||
* For larger images, try 1-10 range or even higher.
|
||||
* Pay attention that number of detected point decreases quickly per octave
|
||||
* for particular image. Algorithm finds more points in case of small octave number.
|
||||
* If method detects nothing, reduce octave start value.
|
||||
* In addition, if many feature points are required (the largest possible amount),
|
||||
* use the lowest octave start value (1) and wide octave range.
|
||||
*
|
||||
* @note Typical threshold's value is 0,001. It's pretty good for all images.
|
||||
* But this value depends on image's nature and may be various in each particular case.
|
||||
* For example, value can be 0,002 or 0,005.
|
||||
* Notice that number of detected points is larger if threshold is lower.
|
||||
* But with high threshold feature points will be better - "stronger", more "unique" and distinctive.
|
||||
*
|
||||
* Feel free to experiment with parameters, because character, robustness and number of points
|
||||
* entirely depend on provided range of octaves and threshold.
|
||||
*
|
||||
* NOTICE that every octave requires time to compute. Use a little range
|
||||
* or only one octave, if execution time is significant.
|
||||
*
|
||||
* @return CE_None or CE_Failure if error occurs.
|
||||
*/
|
||||
|
||||
static std::vector<GDALFeaturePoint> *
|
||||
GatherFeaturePoints(GDALDataset* poDataset, int* panBands,
|
||||
int nOctaveStart, int nOctaveEnd, double dfThreshold)
|
||||
{
|
||||
if (poDataset == NULL)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined, "GDALDataset isn't specified");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (panBands == NULL)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"Raster bands are not specified");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (nOctaveStart <= 0 || nOctaveEnd < 0 ||
|
||||
nOctaveStart > nOctaveEnd)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"Octave numbers are invalid");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dfThreshold < 0)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"Threshold have to be greater than zero");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GDALRasterBand *poRstRedBand = poDataset->GetRasterBand(panBands[0]);
|
||||
GDALRasterBand *poRstGreenBand = poDataset->GetRasterBand(panBands[1]);
|
||||
GDALRasterBand *poRstBlueBand = poDataset->GetRasterBand(panBands[2]);
|
||||
|
||||
int nWidth = poRstRedBand->GetXSize();
|
||||
int nHeight = poRstRedBand->GetYSize();
|
||||
|
||||
// Allocate memory for grayscale image
|
||||
double **padfImg = NULL;
|
||||
padfImg = new double*[nHeight];
|
||||
for (int i = 0; i < nHeight; i++)
|
||||
padfImg[i] = new double[nWidth];
|
||||
|
||||
// Create grayscale image
|
||||
GDALSimpleSURF::ConvertRGBToLuminosity(
|
||||
poRstRedBand, poRstGreenBand, poRstBlueBand, nWidth, nHeight,
|
||||
padfImg, nHeight, nWidth);
|
||||
|
||||
// Prepare integral image
|
||||
GDALIntegralImage *poImg = new GDALIntegralImage();
|
||||
poImg->Initialize((const double**)padfImg, nHeight, nWidth);
|
||||
|
||||
// Get feature points
|
||||
GDALSimpleSURF *poSurf = new GDALSimpleSURF(nOctaveStart, nOctaveEnd);
|
||||
|
||||
std::vector<GDALFeaturePoint> *poCollection =
|
||||
poSurf->ExtractFeaturePoints(poImg, dfThreshold);
|
||||
|
||||
// Clean up
|
||||
delete poImg;
|
||||
delete poSurf;
|
||||
|
||||
for (int i = 0; i < nHeight; i++)
|
||||
delete[] padfImg[i];
|
||||
|
||||
delete[] padfImg;
|
||||
|
||||
return poCollection;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALComputeMatchingPoints() */
|
||||
/************************************************************************/
|
||||
|
||||
GDAL_GCP CPL_DLL *
|
||||
GDALComputeMatchingPoints( GDALDatasetH hFirstImage,
|
||||
GDALDatasetH hSecondImage,
|
||||
char **papszOptions,
|
||||
int *pnGCPCount )
|
||||
{
|
||||
*pnGCPCount = 0;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Override default algorithm parameters. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int nOctaveStart, nOctaveEnd;
|
||||
double dfSURFThreshold;
|
||||
double dfMatchingThreshold = 0.015;
|
||||
|
||||
nOctaveStart =atoi(CSLFetchNameValueDef(papszOptions, "OCTAVE_START", "2"));
|
||||
nOctaveEnd = atoi(CSLFetchNameValueDef(papszOptions, "OCTAVE_END", "2"));
|
||||
|
||||
dfSURFThreshold = CPLAtof(
|
||||
CSLFetchNameValueDef(papszOptions, "SURF_THRESHOLD", "0.001"));
|
||||
dfMatchingThreshold = CPLAtof(
|
||||
CSLFetchNameValueDef(papszOptions, "MATCHING_THRESHOLD", "0.015"));
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Identify the bands to use. For now we are effectively */
|
||||
/* limited to using RGB input so if we have one band only treat */
|
||||
/* it as red=green=blue=band 1. Disallow non eightbit imagery. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int anBandMap1[3], anBandMap2[3];
|
||||
|
||||
if( GDALGetRasterCount(hFirstImage) >= 3 )
|
||||
{
|
||||
anBandMap1[0] = 1;
|
||||
anBandMap1[1] = 2;
|
||||
anBandMap1[2] = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
anBandMap1[0] = anBandMap1[1] = anBandMap1[2] = 1;
|
||||
}
|
||||
|
||||
if( GDALGetRasterCount(hSecondImage) >= 3 )
|
||||
{
|
||||
anBandMap2[0] = 1;
|
||||
anBandMap2[1] = 2;
|
||||
anBandMap2[2] = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
anBandMap2[0] = anBandMap2[1] = anBandMap2[2] = 1;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Collect reference points on each image. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
std::vector<GDALFeaturePoint> *poFPCollection1 =
|
||||
GatherFeaturePoints((GDALDataset *) hFirstImage, anBandMap1,
|
||||
nOctaveStart, nOctaveEnd, dfSURFThreshold);
|
||||
if( poFPCollection1 == NULL )
|
||||
return NULL;
|
||||
|
||||
std::vector<GDALFeaturePoint> *poFPCollection2 =
|
||||
GatherFeaturePoints((GDALDataset *) hSecondImage, anBandMap2,
|
||||
nOctaveStart, nOctaveEnd,
|
||||
dfSURFThreshold);
|
||||
|
||||
if( poFPCollection2 == NULL )
|
||||
return NULL;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Try to find corresponding locations. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLErr eErr;
|
||||
std::vector<GDALFeaturePoint *> oMatchPairs;
|
||||
|
||||
eErr = GDALSimpleSURF::MatchFeaturePoints(
|
||||
&oMatchPairs, poFPCollection1, poFPCollection2,
|
||||
dfMatchingThreshold );
|
||||
|
||||
if( eErr != CE_None )
|
||||
return NULL;
|
||||
|
||||
|
||||
*pnGCPCount = oMatchPairs.size() / 2;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Translate these into GCPs - but with the output coordinate */
|
||||
/* system being pixel/line on the second image. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GDAL_GCP *pasGCPList = (GDAL_GCP*) CPLCalloc(*pnGCPCount, sizeof(GDAL_GCP));
|
||||
|
||||
GDALInitGCPs(*pnGCPCount, pasGCPList);
|
||||
|
||||
for (int i=0; i < *pnGCPCount; i++)
|
||||
{
|
||||
GDALFeaturePoint *poPoint1 = oMatchPairs[i*2 ];
|
||||
GDALFeaturePoint *poPoint2 = oMatchPairs[i*2+1];
|
||||
|
||||
pasGCPList[i].dfGCPPixel = poPoint1->GetX() + 0.5;
|
||||
pasGCPList[i].dfGCPLine = poPoint1->GetY() + 0.5;
|
||||
|
||||
pasGCPList[i].dfGCPX = poPoint2->GetX() + 0.5;
|
||||
pasGCPList[i].dfGCPY = poPoint2->GetY() + 0.5;
|
||||
pasGCPList[i].dfGCPZ = 0.0;
|
||||
}
|
||||
|
||||
// Cleanup the feature point lists.
|
||||
delete poFPCollection1;
|
||||
delete poFPCollection2;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Optionally transform into the georef coordinates of the */
|
||||
/* output image. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int bGeorefOutput =
|
||||
CSLTestBoolean(CSLFetchNameValueDef(papszOptions,"OUTPUT_GEOREF","NO"));
|
||||
|
||||
if( bGeorefOutput )
|
||||
{
|
||||
double adfGeoTransform[6];
|
||||
|
||||
GDALGetGeoTransform( hSecondImage, adfGeoTransform );
|
||||
|
||||
for (int i=0; i < *pnGCPCount; i++)
|
||||
{
|
||||
GDALApplyGeoTransform(adfGeoTransform,
|
||||
pasGCPList[i].dfGCPX,
|
||||
pasGCPList[i].dfGCPY,
|
||||
&(pasGCPList[i].dfGCPX),
|
||||
&(pasGCPList[i].dfGCPY));
|
||||
}
|
||||
}
|
||||
|
||||
return pasGCPList;
|
||||
}
|
||||
1126
bazaar/plugin/gdal/alg/gdalmediancut.cpp
Normal file
1126
bazaar/plugin/gdal/alg/gdalmediancut.cpp
Normal file
File diff suppressed because it is too large
Load diff
560
bazaar/plugin/gdal/alg/gdalproximity.cpp
Normal file
560
bazaar/plugin/gdal/alg/gdalproximity.cpp
Normal file
|
|
@ -0,0 +1,560 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdalproximity.cpp 28882 2015-04-09 15:59:38Z rouault $
|
||||
*
|
||||
* Project: GDAL
|
||||
* Purpose: Compute each pixel's proximity to a set of target pixels.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2008, Frank Warmerdam
|
||||
* Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_alg.h"
|
||||
#include "cpl_conv.h"
|
||||
#include "cpl_string.h"
|
||||
|
||||
CPL_CVSID("$Id: gdalproximity.cpp 28882 2015-04-09 15:59:38Z rouault $");
|
||||
|
||||
static CPLErr
|
||||
ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY,
|
||||
int bForward, int iLine, int nXSize, double nMaxDist,
|
||||
float *pafProximity, double *pdfSrcNoDataValue,
|
||||
int nTargetValues, int *panTargetValues );
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALComputeProximity() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
Compute the proximity of all pixels in the image to a set of pixels in the source image.
|
||||
|
||||
This function attempts to compute the proximity of all pixels in
|
||||
the image to a set of pixels in the source image. The following
|
||||
options are used to define the behavior of the function. By
|
||||
default all non-zero pixels in hSrcBand will be considered the
|
||||
"target", and all proximities will be computed in pixels. Note
|
||||
that target pixels are set to the value corresponding to a distance
|
||||
of zero.
|
||||
|
||||
The progress function args may be NULL or a valid progress reporting function
|
||||
such as GDALTermProgress/NULL.
|
||||
|
||||
Options:
|
||||
|
||||
VALUES=n[,n]*
|
||||
|
||||
A list of target pixel values to measure the distance from. If this
|
||||
option is not provided proximity will be computed from non-zero
|
||||
pixel values. Currently pixel values are internally processed as
|
||||
integers.
|
||||
|
||||
DISTUNITS=[PIXEL]/GEO
|
||||
|
||||
Indicates whether distances will be computed in pixel units or
|
||||
in georeferenced units. The default is pixel units. This also
|
||||
determines the interpretation of MAXDIST.
|
||||
|
||||
MAXDIST=n
|
||||
|
||||
The maximum distance to search. Proximity distances greater than
|
||||
this value will not be computed. Instead output pixels will be
|
||||
set to a nodata value.
|
||||
|
||||
NODATA=n
|
||||
|
||||
The NODATA value to use on the output band for pixels that are
|
||||
beyond MAXDIST. If not provided, the hProximityBand will be
|
||||
queried for a nodata value. If one is not found, 65535 will be used.
|
||||
|
||||
USE_INPUT_NODATA=YES/NO
|
||||
|
||||
If this option is set, the input data set no-data value will be
|
||||
respected. Leaving no data pixels in the input as no data pixels in
|
||||
the proximity output.
|
||||
|
||||
FIXED_BUF_VAL=n
|
||||
|
||||
If this option is set, all pixels within the MAXDIST threadhold are
|
||||
set to this fixed value instead of to a proximity distance.
|
||||
*/
|
||||
|
||||
|
||||
CPLErr CPL_STDCALL
|
||||
GDALComputeProximity( GDALRasterBandH hSrcBand,
|
||||
GDALRasterBandH hProximityBand,
|
||||
char **papszOptions,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg )
|
||||
|
||||
{
|
||||
int nXSize, nYSize, i, bFixedBufVal = FALSE;
|
||||
const char *pszOpt;
|
||||
double dfMaxDist;
|
||||
double dfFixedBufVal = 0.0;
|
||||
|
||||
VALIDATE_POINTER1( hSrcBand, "GDALComputeProximity", CE_Failure );
|
||||
VALIDATE_POINTER1( hProximityBand, "GDALComputeProximity", CE_Failure );
|
||||
|
||||
if( pfnProgress == NULL )
|
||||
pfnProgress = GDALDummyProgress;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Are we using pixels or georeferenced coordinates for distances? */
|
||||
/* -------------------------------------------------------------------- */
|
||||
double dfDistMult = 1.0;
|
||||
pszOpt = CSLFetchNameValue( papszOptions, "DISTUNITS" );
|
||||
if( pszOpt )
|
||||
{
|
||||
if( EQUAL(pszOpt,"GEO") )
|
||||
{
|
||||
GDALDatasetH hSrcDS = GDALGetBandDataset( hSrcBand );
|
||||
if( hSrcDS )
|
||||
{
|
||||
double adfGeoTransform[6];
|
||||
|
||||
GDALGetGeoTransform( hSrcDS, adfGeoTransform );
|
||||
if( ABS(adfGeoTransform[1]) != ABS(adfGeoTransform[5]) )
|
||||
CPLError( CE_Warning, CPLE_AppDefined,
|
||||
"Pixels not square, distances will be inaccurate." );
|
||||
dfDistMult = ABS(adfGeoTransform[1]);
|
||||
}
|
||||
}
|
||||
else if( !EQUAL(pszOpt,"PIXEL") )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Unrecognised DISTUNITS value '%s', should be GEO or PIXEL.",
|
||||
pszOpt );
|
||||
return CE_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* What is our maxdist value? */
|
||||
/* -------------------------------------------------------------------- */
|
||||
pszOpt = CSLFetchNameValue( papszOptions, "MAXDIST" );
|
||||
if( pszOpt )
|
||||
dfMaxDist = CPLAtof(pszOpt) / dfDistMult;
|
||||
else
|
||||
dfMaxDist = GDALGetRasterBandXSize(hSrcBand) + GDALGetRasterBandYSize(hSrcBand);
|
||||
|
||||
CPLDebug( "GDAL", "MAXDIST=%g, DISTMULT=%g", dfMaxDist, dfDistMult );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Verify the source and destination are compatible. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
nXSize = GDALGetRasterBandXSize( hSrcBand );
|
||||
nYSize = GDALGetRasterBandYSize( hSrcBand );
|
||||
if( nXSize != GDALGetRasterBandXSize( hProximityBand )
|
||||
|| nYSize != GDALGetRasterBandYSize( hProximityBand ))
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Source and proximity bands are not the same size." );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Get input NODATA value. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
double dfSrcNoDataValue = 0.0;
|
||||
double *pdfSrcNoData = NULL;
|
||||
if( CSLFetchBoolean( papszOptions, "USE_INPUT_NODATA", FALSE ) )
|
||||
{
|
||||
int bSrcHasNoData = 0;
|
||||
dfSrcNoDataValue = GDALGetRasterNoDataValue( hSrcBand, &bSrcHasNoData );
|
||||
if( bSrcHasNoData )
|
||||
pdfSrcNoData = &dfSrcNoDataValue;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Get output NODATA value. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
float fNoDataValue;
|
||||
pszOpt = CSLFetchNameValue( papszOptions, "NODATA" );
|
||||
if( pszOpt != NULL )
|
||||
fNoDataValue = (float) CPLAtof(pszOpt);
|
||||
else
|
||||
{
|
||||
int bSuccess;
|
||||
|
||||
fNoDataValue = (float) GDALGetRasterNoDataValue( hProximityBand, &bSuccess );
|
||||
if( !bSuccess )
|
||||
fNoDataValue = 65535.0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Is there a fixed value we wish to force the buffer area to? */
|
||||
/* -------------------------------------------------------------------- */
|
||||
pszOpt = CSLFetchNameValue( papszOptions, "FIXED_BUF_VAL" );
|
||||
if( pszOpt )
|
||||
{
|
||||
dfFixedBufVal = CPLAtof(pszOpt);
|
||||
bFixedBufVal = TRUE;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Get the target value(s). */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int *panTargetValues = NULL;
|
||||
int nTargetValues = 0;
|
||||
|
||||
pszOpt = CSLFetchNameValue( papszOptions, "VALUES" );
|
||||
if( pszOpt != NULL )
|
||||
{
|
||||
char **papszValuesTokens;
|
||||
|
||||
papszValuesTokens = CSLTokenizeStringComplex( pszOpt, ",", FALSE,FALSE);
|
||||
|
||||
nTargetValues = CSLCount(papszValuesTokens);
|
||||
panTargetValues = (int *) CPLCalloc(sizeof(int),nTargetValues);
|
||||
|
||||
for( i = 0; i < nTargetValues; i++ )
|
||||
panTargetValues[i] = atoi(papszValuesTokens[i]);
|
||||
CSLDestroy( papszValuesTokens );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Initialize progress counter. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( !pfnProgress( 0.0, "", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
CPLFree(panTargetValues);
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* We need a signed type for the working proximity values kept */
|
||||
/* on disk. If our proximity band is not signed, then create a */
|
||||
/* temporary file for this purpose. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GDALRasterBandH hWorkProximityBand = hProximityBand;
|
||||
GDALDatasetH hWorkProximityDS = NULL;
|
||||
GDALDataType eProxType = GDALGetRasterDataType( hProximityBand );
|
||||
int *panNearX = NULL, *panNearY = NULL;
|
||||
float *pafProximity = NULL;
|
||||
GInt32 *panSrcScanline = NULL;
|
||||
int iLine;
|
||||
CPLErr eErr = CE_None;
|
||||
|
||||
if( eProxType == GDT_Byte
|
||||
|| eProxType == GDT_UInt16
|
||||
|| eProxType == GDT_UInt32 )
|
||||
{
|
||||
GDALDriverH hDriver = GDALGetDriverByName("GTiff");
|
||||
if (hDriver == NULL)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"GDALComputeProximity needs GTiff driver");
|
||||
eErr = CE_Failure;
|
||||
goto end;
|
||||
}
|
||||
CPLString osTmpFile = CPLGenerateTempFilename( "proximity" );
|
||||
hWorkProximityDS =
|
||||
GDALCreate( hDriver, osTmpFile,
|
||||
nXSize, nYSize, 1, GDT_Float32, NULL );
|
||||
if (hWorkProximityDS == NULL)
|
||||
{
|
||||
eErr = CE_Failure;
|
||||
goto end;
|
||||
}
|
||||
hWorkProximityBand = GDALGetRasterBand( hWorkProximityDS, 1 );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Allocate buffer for two scanlines of distances as floats */
|
||||
/* (the current and last line). */
|
||||
/* -------------------------------------------------------------------- */
|
||||
pafProximity = (float *) VSIMalloc2(sizeof(float), nXSize);
|
||||
panNearX = (int *) VSIMalloc2(sizeof(int), nXSize);
|
||||
panNearY = (int *) VSIMalloc2(sizeof(int), nXSize);
|
||||
panSrcScanline = (GInt32 *) VSIMalloc2(sizeof(GInt32), nXSize);
|
||||
|
||||
if( pafProximity== NULL
|
||||
|| panNearX == NULL
|
||||
|| panNearY == NULL
|
||||
|| panSrcScanline == NULL)
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_OutOfMemory,
|
||||
"Out of memory allocating working buffers.");
|
||||
eErr = CE_Failure;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Loop from top to bottom of the image. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
for( i = 0; i < nXSize; i++ )
|
||||
panNearX[i] = panNearY[i] = -1;
|
||||
|
||||
for( iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ )
|
||||
{
|
||||
// Read for target values.
|
||||
eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iLine, nXSize, 1,
|
||||
panSrcScanline, nXSize, 1, GDT_Int32, 0, 0 );
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
for( i = 0; i < nXSize; i++ )
|
||||
pafProximity[i] = -1.0;
|
||||
|
||||
// Left to right
|
||||
ProcessProximityLine( panSrcScanline, panNearX, panNearY,
|
||||
TRUE, iLine, nXSize, dfMaxDist, pafProximity,
|
||||
pdfSrcNoData, nTargetValues, panTargetValues );
|
||||
|
||||
// Right to Left
|
||||
ProcessProximityLine( panSrcScanline, panNearX, panNearY,
|
||||
FALSE, iLine, nXSize, dfMaxDist, pafProximity,
|
||||
pdfSrcNoData, nTargetValues, panTargetValues );
|
||||
|
||||
// Write out results.
|
||||
eErr =
|
||||
GDALRasterIO( hWorkProximityBand, GF_Write, 0, iLine, nXSize, 1,
|
||||
pafProximity, nXSize, 1, GDT_Float32, 0, 0 );
|
||||
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
if( !pfnProgress( 0.5 * (iLine+1) / (double) nYSize,
|
||||
"", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
eErr = CE_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Loop from bottom to top of the image. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( i = 0; i < nXSize; i++ )
|
||||
panNearX[i] = panNearY[i] = -1;
|
||||
|
||||
for( iLine = nYSize-1; eErr == CE_None && iLine >= 0; iLine-- )
|
||||
{
|
||||
// Read first pass proximity
|
||||
eErr =
|
||||
GDALRasterIO( hWorkProximityBand, GF_Read, 0, iLine, nXSize, 1,
|
||||
pafProximity, nXSize, 1, GDT_Float32, 0, 0 );
|
||||
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
// Read pixel values.
|
||||
|
||||
eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iLine, nXSize, 1,
|
||||
panSrcScanline, nXSize, 1, GDT_Int32, 0, 0 );
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
// Right to left
|
||||
ProcessProximityLine( panSrcScanline, panNearX, panNearY,
|
||||
FALSE, iLine, nXSize, dfMaxDist, pafProximity,
|
||||
pdfSrcNoData, nTargetValues, panTargetValues );
|
||||
|
||||
// Left to right
|
||||
ProcessProximityLine( panSrcScanline, panNearX, panNearY,
|
||||
TRUE, iLine, nXSize, dfMaxDist, pafProximity,
|
||||
pdfSrcNoData, nTargetValues, panTargetValues );
|
||||
|
||||
// Final post processing of distances.
|
||||
for( i = 0; i < nXSize; i++ )
|
||||
{
|
||||
if( pafProximity[i] < 0.0 )
|
||||
pafProximity[i] = fNoDataValue;
|
||||
else if( pafProximity[i] > 0.0 )
|
||||
{
|
||||
if( bFixedBufVal )
|
||||
pafProximity[i] = (float) dfFixedBufVal;
|
||||
else
|
||||
pafProximity[i] = (float)(pafProximity[i] * dfDistMult);
|
||||
}
|
||||
}
|
||||
|
||||
// Write out results.
|
||||
eErr =
|
||||
GDALRasterIO( hProximityBand, GF_Write, 0, iLine, nXSize, 1,
|
||||
pafProximity, nXSize, 1, GDT_Float32, 0, 0 );
|
||||
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
if( !pfnProgress( 0.5 + 0.5 * (nYSize-iLine) / (double) nYSize,
|
||||
"", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
eErr = CE_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Cleanup */
|
||||
/* -------------------------------------------------------------------- */
|
||||
end:
|
||||
CPLFree( panNearX );
|
||||
CPLFree( panNearY );
|
||||
CPLFree( panSrcScanline );
|
||||
CPLFree( pafProximity );
|
||||
CPLFree(panTargetValues);
|
||||
|
||||
if( hWorkProximityDS != NULL )
|
||||
{
|
||||
CPLString osProxFile = GDALGetDescription( hWorkProximityDS );
|
||||
GDALClose( hWorkProximityDS );
|
||||
GDALDeleteDataset( GDALGetDriverByName( "GTiff" ), osProxFile );
|
||||
}
|
||||
|
||||
return eErr;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ProcessProximityLine() */
|
||||
/************************************************************************/
|
||||
|
||||
static CPLErr
|
||||
ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY,
|
||||
int bForward, int iLine, int nXSize, double dfMaxDist,
|
||||
float *pafProximity, double *pdfSrcNoDataValue,
|
||||
int nTargetValues, int *panTargetValues )
|
||||
|
||||
{
|
||||
int iStart, iEnd, iStep, iPixel;
|
||||
|
||||
if( bForward )
|
||||
{
|
||||
iStart = 0;
|
||||
iEnd = nXSize;
|
||||
iStep = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
iStart = nXSize-1;
|
||||
iEnd = -1;
|
||||
iStep = -1;
|
||||
}
|
||||
|
||||
for( iPixel = iStart; iPixel != iEnd; iPixel += iStep )
|
||||
{
|
||||
int bIsTarget = FALSE;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Is the current pixel a target pixel? */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( nTargetValues == 0 )
|
||||
bIsTarget = (panSrcScanline[iPixel] != 0);
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < nTargetValues; i++ )
|
||||
{
|
||||
if( panSrcScanline[iPixel] == panTargetValues[i] )
|
||||
bIsTarget = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if( bIsTarget )
|
||||
{
|
||||
pafProximity[iPixel] = 0.0;
|
||||
panNearX[iPixel] = iPixel;
|
||||
panNearY[iPixel] = iLine;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Are we near(er) to the closest target to the above (below) */
|
||||
/* pixel? */
|
||||
/* -------------------------------------------------------------------- */
|
||||
float fNearDistSq = (float) (MAX(dfMaxDist,nXSize) * MAX(dfMaxDist,nXSize) * 2);
|
||||
float fDistSq;
|
||||
|
||||
if( panNearX[iPixel] != -1 )
|
||||
{
|
||||
fDistSq = (float)
|
||||
((panNearX[iPixel] - iPixel) * (panNearX[iPixel] - iPixel)
|
||||
+ (panNearY[iPixel] - iLine) * (panNearY[iPixel] - iLine));
|
||||
|
||||
if( fDistSq < fNearDistSq )
|
||||
{
|
||||
fNearDistSq = fDistSq;
|
||||
}
|
||||
else
|
||||
{
|
||||
panNearX[iPixel] = -1;
|
||||
panNearY[iPixel] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Are we near(er) to the closest target to the left (right) */
|
||||
/* pixel? */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int iLast = iPixel-iStep;
|
||||
|
||||
if( iPixel != iStart && panNearX[iLast] != -1 )
|
||||
{
|
||||
fDistSq = (float)
|
||||
((panNearX[iLast] - iPixel) * (panNearX[iLast] - iPixel)
|
||||
+ (panNearY[iLast] - iLine) * (panNearY[iLast] - iLine));
|
||||
|
||||
if( fDistSq < fNearDistSq )
|
||||
{
|
||||
fNearDistSq = fDistSq;
|
||||
panNearX[iPixel] = panNearX[iLast];
|
||||
panNearY[iPixel] = panNearY[iLast];
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Are we near(er) to the closest target to the topright */
|
||||
/* (bottom left) pixel? */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int iTR = iPixel+iStep;
|
||||
|
||||
if( iTR != iEnd && panNearX[iTR] != -1 )
|
||||
{
|
||||
fDistSq = (float)
|
||||
((panNearX[iTR] - iPixel) * (panNearX[iTR] - iPixel)
|
||||
+ (panNearY[iTR] - iLine) * (panNearY[iTR] - iLine));
|
||||
|
||||
if( fDistSq < fNearDistSq )
|
||||
{
|
||||
fNearDistSq = fDistSq;
|
||||
panNearX[iPixel] = panNearX[iTR];
|
||||
panNearY[iPixel] = panNearY[iTR];
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Update our proximity value. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( panNearX[iPixel] != -1
|
||||
&& (pdfSrcNoDataValue == NULL
|
||||
|| panSrcScanline[iPixel] != *pdfSrcNoDataValue)
|
||||
&& fNearDistSq <= dfMaxDist * dfMaxDist
|
||||
&& (pafProximity[iPixel] < 0
|
||||
|| fNearDistSq < pafProximity[iPixel] * pafProximity[iPixel]) )
|
||||
pafProximity[iPixel] = sqrt(fNearDistSq);
|
||||
}
|
||||
|
||||
return CE_None;
|
||||
}
|
||||
250
bazaar/plugin/gdal/alg/gdalrasterfpolygonenumerator.cpp
Normal file
250
bazaar/plugin/gdal/alg/gdalrasterfpolygonenumerator.cpp
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdalrasterfpolygonenumerator.cpp 24379 2012-05-04 01:26:19Z warmerdam $
|
||||
*
|
||||
* Project: GDAL
|
||||
* Purpose: Version of Raster Polygon Enumerator using float buffers.
|
||||
* Author: Jorge Arevalo, jorge.arevalo@deimos-space.com. Most of the code
|
||||
* taken from GDALRasterFPolygonEnumerator, by Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2011, Jorge Arevalo
|
||||
* Copyright (c) 2008, Frank Warmerdam
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_alg_priv.h"
|
||||
#include "cpl_conv.h"
|
||||
#include <vector>
|
||||
|
||||
CPL_CVSID("$Id: gdalrasterfpolygonenumerator.cpp 24379 2012-05-04 01:26:19Z warmerdam $");
|
||||
|
||||
#ifdef OGR_ENABLED
|
||||
/************************************************************************/
|
||||
/* GDALRasterFPolygonEnumerator() */
|
||||
/************************************************************************/
|
||||
|
||||
GDALRasterFPolygonEnumerator::GDALRasterFPolygonEnumerator(
|
||||
int nConnectedness )
|
||||
|
||||
{
|
||||
panPolyIdMap = NULL;
|
||||
pafPolyValue = NULL;
|
||||
nNextPolygonId = 0;
|
||||
nPolyAlloc = 0;
|
||||
this->nConnectedness = nConnectedness;
|
||||
CPLAssert( nConnectedness == 4 || nConnectedness == 8 );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ~GDALRasterFPolygonEnumerator() */
|
||||
/************************************************************************/
|
||||
|
||||
GDALRasterFPolygonEnumerator::~GDALRasterFPolygonEnumerator()
|
||||
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Clear() */
|
||||
/************************************************************************/
|
||||
|
||||
void GDALRasterFPolygonEnumerator::Clear()
|
||||
|
||||
{
|
||||
CPLFree( panPolyIdMap );
|
||||
CPLFree( pafPolyValue );
|
||||
|
||||
panPolyIdMap = NULL;
|
||||
pafPolyValue = NULL;
|
||||
|
||||
nNextPolygonId = 0;
|
||||
nPolyAlloc = 0;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* MergePolygon() */
|
||||
/* */
|
||||
/* Update the polygon map to indicate the merger of two polygons. */
|
||||
/************************************************************************/
|
||||
|
||||
void GDALRasterFPolygonEnumerator::MergePolygon( int nSrcId, int nDstId )
|
||||
|
||||
{
|
||||
while( panPolyIdMap[nDstId] != nDstId )
|
||||
nDstId = panPolyIdMap[nDstId];
|
||||
|
||||
while( panPolyIdMap[nSrcId] != nSrcId )
|
||||
nSrcId = panPolyIdMap[nSrcId];
|
||||
|
||||
if( nSrcId == nDstId )
|
||||
return;
|
||||
|
||||
panPolyIdMap[nSrcId] = nDstId;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* NewPolygon() */
|
||||
/* */
|
||||
/* Allocate a new polygon id, and reallocate the polygon maps */
|
||||
/* if needed. */
|
||||
/************************************************************************/
|
||||
|
||||
int GDALRasterFPolygonEnumerator::NewPolygon( float fValue )
|
||||
|
||||
{
|
||||
int nPolyId = nNextPolygonId;
|
||||
|
||||
if( nNextPolygonId >= nPolyAlloc )
|
||||
{
|
||||
nPolyAlloc = nPolyAlloc * 2 + 20;
|
||||
panPolyIdMap = (GInt32 *) CPLRealloc(panPolyIdMap,nPolyAlloc*4);
|
||||
pafPolyValue = (float *) CPLRealloc(pafPolyValue,nPolyAlloc*4);
|
||||
}
|
||||
|
||||
nNextPolygonId++;
|
||||
|
||||
panPolyIdMap[nPolyId] = nPolyId;
|
||||
pafPolyValue[nPolyId] = fValue;
|
||||
|
||||
return nPolyId;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* CompleteMerges() */
|
||||
/* */
|
||||
/* Make a pass through the maps, ensuring every polygon id */
|
||||
/* points to the final id it should use, not an intermediate */
|
||||
/* value. */
|
||||
/************************************************************************/
|
||||
|
||||
void GDALRasterFPolygonEnumerator::CompleteMerges()
|
||||
|
||||
{
|
||||
int iPoly;
|
||||
int nFinalPolyCount = 0;
|
||||
|
||||
for( iPoly = 0; iPoly < nNextPolygonId; iPoly++ )
|
||||
{
|
||||
while( panPolyIdMap[iPoly]
|
||||
!= panPolyIdMap[panPolyIdMap[iPoly]] )
|
||||
panPolyIdMap[iPoly] = panPolyIdMap[panPolyIdMap[iPoly]];
|
||||
|
||||
if( panPolyIdMap[iPoly] == iPoly )
|
||||
nFinalPolyCount++;
|
||||
}
|
||||
|
||||
CPLDebug( "GDALRasterFPolygonEnumerator",
|
||||
"Counted %d polygon fragments forming %d final polygons.",
|
||||
nNextPolygonId, nFinalPolyCount );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ProcessLine() */
|
||||
/* */
|
||||
/* Assign ids to polygons, one line at a time. */
|
||||
/************************************************************************/
|
||||
|
||||
void GDALRasterFPolygonEnumerator::ProcessLine(
|
||||
float *pafLastLineVal, float *pafThisLineVal,
|
||||
GInt32 *panLastLineId, GInt32 *panThisLineId,
|
||||
int nXSize )
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Special case for the first line. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( pafLastLineVal == NULL )
|
||||
{
|
||||
for( i=0; i < nXSize; i++ )
|
||||
{
|
||||
if( i == 0 || !GDALFloatEquals(pafThisLineVal[i], pafThisLineVal[i-1]) )
|
||||
{
|
||||
panThisLineId[i] = NewPolygon( pafThisLineVal[i] );
|
||||
}
|
||||
else
|
||||
panThisLineId[i] = panThisLineId[i-1];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Process each pixel comparing to the previous pixel, and to */
|
||||
/* the last line. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( i = 0; i < nXSize; i++ )
|
||||
{
|
||||
if( i > 0 && GDALFloatEquals(pafThisLineVal[i], pafThisLineVal[i-1]) )
|
||||
{
|
||||
panThisLineId[i] = panThisLineId[i-1];
|
||||
|
||||
if( GDALFloatEquals(pafLastLineVal[i], pafThisLineVal[i])
|
||||
&& (panPolyIdMap[panLastLineId[i]]
|
||||
!= panPolyIdMap[panThisLineId[i]]) )
|
||||
{
|
||||
MergePolygon( panLastLineId[i], panThisLineId[i] );
|
||||
}
|
||||
|
||||
if( nConnectedness == 8
|
||||
&& pafLastLineVal[i-1] == pafThisLineVal[i]
|
||||
&& (panPolyIdMap[panLastLineId[i-1]]
|
||||
!= panPolyIdMap[panThisLineId[i]]) )
|
||||
{
|
||||
MergePolygon( panLastLineId[i-1], panThisLineId[i] );
|
||||
}
|
||||
|
||||
if( nConnectedness == 8 && i < nXSize-1
|
||||
&& pafLastLineVal[i+1] == pafThisLineVal[i]
|
||||
&& (panPolyIdMap[panLastLineId[i+1]]
|
||||
!= panPolyIdMap[panThisLineId[i]]) )
|
||||
{
|
||||
MergePolygon( panLastLineId[i+1], panThisLineId[i] );
|
||||
}
|
||||
}
|
||||
else if( GDALFloatEquals(pafLastLineVal[i], pafThisLineVal[i]) )
|
||||
{
|
||||
panThisLineId[i] = panLastLineId[i];
|
||||
}
|
||||
else if( i > 0 && nConnectedness == 8
|
||||
&& GDALFloatEquals(pafLastLineVal[i-1], pafThisLineVal[i]) )
|
||||
{
|
||||
panThisLineId[i] = panLastLineId[i-1];
|
||||
|
||||
if( i < nXSize-1 && pafLastLineVal[i+1] == pafThisLineVal[i]
|
||||
&& (panPolyIdMap[panLastLineId[i+1]]
|
||||
!= panPolyIdMap[panThisLineId[i]]) )
|
||||
{
|
||||
MergePolygon( panLastLineId[i+1], panThisLineId[i] );
|
||||
}
|
||||
}
|
||||
else if( i < nXSize-1 && nConnectedness == 8
|
||||
&& GDALFloatEquals(pafLastLineVal[i+1], pafThisLineVal[i]) )
|
||||
{
|
||||
panThisLineId[i] = panLastLineId[i+1];
|
||||
}
|
||||
else
|
||||
panThisLineId[i] =
|
||||
NewPolygon( pafThisLineVal[i] );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
1323
bazaar/plugin/gdal/alg/gdalrasterize.cpp
Normal file
1323
bazaar/plugin/gdal/alg/gdalrasterize.cpp
Normal file
File diff suppressed because it is too large
Load diff
255
bazaar/plugin/gdal/alg/gdalrasterpolygonenumerator.cpp
Normal file
255
bazaar/plugin/gdal/alg/gdalrasterpolygonenumerator.cpp
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdalrasterpolygonenumerator.cpp 28826 2015-03-30 17:51:14Z rouault $
|
||||
*
|
||||
* Project: GDAL
|
||||
* Purpose: Raster Polygon Enumerator
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2008, Frank Warmerdam
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_alg_priv.h"
|
||||
#include "cpl_conv.h"
|
||||
#include <vector>
|
||||
|
||||
CPL_CVSID("$Id: gdalrasterpolygonenumerator.cpp 28826 2015-03-30 17:51:14Z rouault $");
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALRasterPolygonEnumerator() */
|
||||
/************************************************************************/
|
||||
|
||||
GDALRasterPolygonEnumerator::GDALRasterPolygonEnumerator(
|
||||
int nConnectedness )
|
||||
|
||||
{
|
||||
panPolyIdMap = NULL;
|
||||
panPolyValue = NULL;
|
||||
nNextPolygonId = 0;
|
||||
nPolyAlloc = 0;
|
||||
this->nConnectedness = nConnectedness;
|
||||
CPLAssert( nConnectedness == 4 || nConnectedness == 8 );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ~GDALRasterPolygonEnumerator() */
|
||||
/************************************************************************/
|
||||
|
||||
GDALRasterPolygonEnumerator::~GDALRasterPolygonEnumerator()
|
||||
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Clear() */
|
||||
/************************************************************************/
|
||||
|
||||
void GDALRasterPolygonEnumerator::Clear()
|
||||
|
||||
{
|
||||
CPLFree( panPolyIdMap );
|
||||
CPLFree( panPolyValue );
|
||||
|
||||
panPolyIdMap = NULL;
|
||||
panPolyValue = NULL;
|
||||
|
||||
nNextPolygonId = 0;
|
||||
nPolyAlloc = 0;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* MergePolygon() */
|
||||
/* */
|
||||
/* Update the polygon map to indicate the merger of two polygons. */
|
||||
/************************************************************************/
|
||||
|
||||
void GDALRasterPolygonEnumerator::MergePolygon( int nSrcId, int nDstId )
|
||||
|
||||
{
|
||||
while( panPolyIdMap[nDstId] != nDstId )
|
||||
nDstId = panPolyIdMap[nDstId];
|
||||
|
||||
while( panPolyIdMap[nSrcId] != nSrcId )
|
||||
nSrcId = panPolyIdMap[nSrcId];
|
||||
|
||||
if( nSrcId == nDstId )
|
||||
return;
|
||||
|
||||
panPolyIdMap[nSrcId] = nDstId;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* NewPolygon() */
|
||||
/* */
|
||||
/* Allocate a new polygon id, and reallocate the polygon maps */
|
||||
/* if needed. */
|
||||
/************************************************************************/
|
||||
|
||||
int GDALRasterPolygonEnumerator::NewPolygon( GInt32 nValue )
|
||||
|
||||
{
|
||||
int nPolyId = nNextPolygonId;
|
||||
|
||||
if( nNextPolygonId >= nPolyAlloc )
|
||||
{
|
||||
nPolyAlloc = nPolyAlloc * 2 + 20;
|
||||
panPolyIdMap = (GInt32 *) CPLRealloc(panPolyIdMap,nPolyAlloc*4);
|
||||
panPolyValue = (GInt32 *) CPLRealloc(panPolyValue,nPolyAlloc*4);
|
||||
}
|
||||
|
||||
nNextPolygonId++;
|
||||
|
||||
panPolyIdMap[nPolyId] = nPolyId;
|
||||
panPolyValue[nPolyId] = nValue;
|
||||
|
||||
return nPolyId;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* CompleteMerges() */
|
||||
/* */
|
||||
/* Make a pass through the maps, ensuring every polygon id */
|
||||
/* points to the final id it should use, not an intermediate */
|
||||
/* value. */
|
||||
/************************************************************************/
|
||||
|
||||
void GDALRasterPolygonEnumerator::CompleteMerges()
|
||||
|
||||
{
|
||||
int iPoly;
|
||||
int nFinalPolyCount = 0;
|
||||
|
||||
for( iPoly = 0; iPoly < nNextPolygonId; iPoly++ )
|
||||
{
|
||||
while( panPolyIdMap[iPoly]
|
||||
!= panPolyIdMap[panPolyIdMap[iPoly]] )
|
||||
panPolyIdMap[iPoly] = panPolyIdMap[panPolyIdMap[iPoly]];
|
||||
|
||||
if( panPolyIdMap[iPoly] == iPoly )
|
||||
nFinalPolyCount++;
|
||||
}
|
||||
|
||||
CPLDebug( "GDALRasterPolygonEnumerator",
|
||||
"Counted %d polygon fragments forming %d final polygons.",
|
||||
nNextPolygonId, nFinalPolyCount );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ProcessLine() */
|
||||
/* */
|
||||
/* Assign ids to polygons, one line at a time. */
|
||||
/************************************************************************/
|
||||
|
||||
void GDALRasterPolygonEnumerator::ProcessLine(
|
||||
GInt32 *panLastLineVal, GInt32 *panThisLineVal,
|
||||
GInt32 *panLastLineId, GInt32 *panThisLineId,
|
||||
int nXSize )
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Special case for the first line. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( panLastLineVal == NULL )
|
||||
{
|
||||
for( i=0; i < nXSize; i++ )
|
||||
{
|
||||
if( panThisLineVal[i] == GP_NODATA_MARKER )
|
||||
{
|
||||
panThisLineId[i] = -1;
|
||||
}
|
||||
else if( i == 0 || panThisLineVal[i] != panThisLineVal[i-1] )
|
||||
{
|
||||
panThisLineId[i] = NewPolygon( panThisLineVal[i] );
|
||||
}
|
||||
else
|
||||
panThisLineId[i] = panThisLineId[i-1];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Process each pixel comparing to the previous pixel, and to */
|
||||
/* the last line. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( i = 0; i < nXSize; i++ )
|
||||
{
|
||||
if( panThisLineVal[i] == GP_NODATA_MARKER )
|
||||
{
|
||||
panThisLineId[i] = -1;
|
||||
}
|
||||
else if( i > 0 && panThisLineVal[i] == panThisLineVal[i-1] )
|
||||
{
|
||||
panThisLineId[i] = panThisLineId[i-1];
|
||||
|
||||
if( panLastLineVal[i] == panThisLineVal[i]
|
||||
&& (panPolyIdMap[panLastLineId[i]]
|
||||
!= panPolyIdMap[panThisLineId[i]]) )
|
||||
{
|
||||
MergePolygon( panLastLineId[i], panThisLineId[i] );
|
||||
}
|
||||
|
||||
if( nConnectedness == 8
|
||||
&& panLastLineVal[i-1] == panThisLineVal[i]
|
||||
&& (panPolyIdMap[panLastLineId[i-1]]
|
||||
!= panPolyIdMap[panThisLineId[i]]) )
|
||||
{
|
||||
MergePolygon( panLastLineId[i-1], panThisLineId[i] );
|
||||
}
|
||||
|
||||
if( nConnectedness == 8 && i < nXSize-1
|
||||
&& panLastLineVal[i+1] == panThisLineVal[i]
|
||||
&& (panPolyIdMap[panLastLineId[i+1]]
|
||||
!= panPolyIdMap[panThisLineId[i]]) )
|
||||
{
|
||||
MergePolygon( panLastLineId[i+1], panThisLineId[i] );
|
||||
}
|
||||
}
|
||||
else if( panLastLineVal[i] == panThisLineVal[i] )
|
||||
{
|
||||
panThisLineId[i] = panLastLineId[i];
|
||||
}
|
||||
else if( i > 0 && nConnectedness == 8
|
||||
&& panLastLineVal[i-1] == panThisLineVal[i] )
|
||||
{
|
||||
panThisLineId[i] = panLastLineId[i-1];
|
||||
|
||||
if( i < nXSize-1 && panLastLineVal[i+1] == panThisLineVal[i]
|
||||
&& (panPolyIdMap[panLastLineId[i+1]]
|
||||
!= panPolyIdMap[panThisLineId[i]]) )
|
||||
{
|
||||
MergePolygon( panLastLineId[i+1], panThisLineId[i] );
|
||||
}
|
||||
}
|
||||
else if( i < nXSize-1 && nConnectedness == 8
|
||||
&& panLastLineVal[i+1] == panThisLineVal[i] )
|
||||
{
|
||||
panThisLineId[i] = panLastLineId[i+1];
|
||||
}
|
||||
else
|
||||
panThisLineId[i] =
|
||||
NewPolygon( panThisLineVal[i] );
|
||||
}
|
||||
}
|
||||
|
||||
578
bazaar/plugin/gdal/alg/gdalsievefilter.cpp
Normal file
578
bazaar/plugin/gdal/alg/gdalsievefilter.cpp
Normal file
|
|
@ -0,0 +1,578 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdalsievefilter.cpp 27745 2014-09-27 16:38:57Z goatbar $
|
||||
*
|
||||
* Project: GDAL
|
||||
* Purpose: Raster to Polygon Converter
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2008, Frank Warmerdam
|
||||
* Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_alg_priv.h"
|
||||
#include "cpl_conv.h"
|
||||
#include <vector>
|
||||
|
||||
CPL_CVSID("$Id: gdalsievefilter.cpp 27745 2014-09-27 16:38:57Z goatbar $");
|
||||
|
||||
#define GP_NODATA_MARKER -51502112
|
||||
#define MY_MAX_INT 2147483647
|
||||
|
||||
/*
|
||||
* General Plan
|
||||
*
|
||||
* 1) make a pass with the polygon enumerator to build up the
|
||||
* polygon map array. Also accumulate polygon size information.
|
||||
*
|
||||
* 2) Identify the polygons that need to be merged.
|
||||
*
|
||||
* 3) Make a pass with the polygon enumerator. For each "to be merged"
|
||||
* polygon keep track of it's largest neighbour.
|
||||
*
|
||||
* 4) Fix up remappings that would go to polygons smaller than the seive
|
||||
* size. Ensure these in term map to the largest neighbour of the
|
||||
* "to be seieved" polygons.
|
||||
*
|
||||
* 5) Make another pass with the polygon enumerator. This time we remap
|
||||
* the actual pixel values of all polygons to be merged.
|
||||
*
|
||||
*/
|
||||
|
||||
/************************************************************************/
|
||||
/* GPMaskImageData() */
|
||||
/* */
|
||||
/* Mask out image pixels to a special nodata value if the mask */
|
||||
/* band is zero. */
|
||||
/************************************************************************/
|
||||
|
||||
static CPLErr
|
||||
GPMaskImageData( GDALRasterBandH hMaskBand, GByte *pabyMaskLine, int iY, int nXSize,
|
||||
GInt32 *panImageLine )
|
||||
|
||||
{
|
||||
CPLErr eErr;
|
||||
|
||||
eErr = GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1,
|
||||
pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0 );
|
||||
if( eErr == CE_None )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < nXSize; i++ )
|
||||
{
|
||||
if( pabyMaskLine[i] == 0 )
|
||||
panImageLine[i] = GP_NODATA_MARKER;
|
||||
}
|
||||
}
|
||||
|
||||
return eErr;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* CompareNeighbour() */
|
||||
/* */
|
||||
/* Compare two neighbouring polygons, and update eaches */
|
||||
/* "biggest neighbour" if the other is larger than it's current */
|
||||
/* largest neighbour. */
|
||||
/* */
|
||||
/* Note that this should end up with each polygon knowing the */
|
||||
/* id of it's largest neighbour. No attempt is made to */
|
||||
/* restrict things to small polygons that we will be merging, */
|
||||
/* nor to exclude assigning "biggest neighbours" that are still */
|
||||
/* smaller than our sieve threshold. */
|
||||
/************************************************************************/
|
||||
|
||||
static inline void CompareNeighbour( int nPolyId1, int nPolyId2,
|
||||
int *panPolyIdMap,
|
||||
int *panPolyValue,
|
||||
std::vector<int> &anPolySizes,
|
||||
std::vector<int> &anBigNeighbour )
|
||||
|
||||
{
|
||||
// make sure we are working with the final merged polygon ids.
|
||||
nPolyId1 = panPolyIdMap[nPolyId1];
|
||||
nPolyId2 = panPolyIdMap[nPolyId2];
|
||||
|
||||
if( nPolyId1 == nPolyId2 )
|
||||
return;
|
||||
|
||||
// nodata polygon do not need neighbours, and cannot be neighbours
|
||||
// to valid polygons.
|
||||
if( panPolyValue[nPolyId1] == GP_NODATA_MARKER
|
||||
|| panPolyValue[nPolyId2] == GP_NODATA_MARKER )
|
||||
return;
|
||||
|
||||
if( anBigNeighbour[nPolyId1] == -1
|
||||
|| anPolySizes[anBigNeighbour[nPolyId1]] < anPolySizes[nPolyId2] )
|
||||
anBigNeighbour[nPolyId1] = nPolyId2;
|
||||
|
||||
if( anBigNeighbour[nPolyId2] == -1
|
||||
|| anPolySizes[anBigNeighbour[nPolyId2]] < anPolySizes[nPolyId1] )
|
||||
anBigNeighbour[nPolyId2] = nPolyId1;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALSieveFilter() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Removes small raster polygons.
|
||||
*
|
||||
* The function removes raster polygons smaller than a provided
|
||||
* threshold size (in pixels) and replaces replaces them with the pixel value
|
||||
* of the largest neighbour polygon.
|
||||
*
|
||||
* Polygon are determined (per GDALRasterPolygonEnumerator) as regions of
|
||||
* the raster where the pixels all have the same value, and that are contiguous
|
||||
* (connected).
|
||||
*
|
||||
* Pixels determined to be "nodata" per hMaskBand will not be treated as part
|
||||
* of a polygon regardless of their pixel values. Nodata areas will never be
|
||||
* changed nor affect polygon sizes.
|
||||
*
|
||||
* Polygons smaller than the threshold with no neighbours that are as large
|
||||
* as the threshold will not be altered. Polygons surrounded by nodata areas
|
||||
* will therefore not be altered.
|
||||
*
|
||||
* The algorithm makes three passes over the input file to enumerate the
|
||||
* polygons and collect limited information about them. Memory use is
|
||||
* proportional to the number of polygons (roughly 24 bytes per polygon), but
|
||||
* is not directly related to the size of the raster. So very large raster
|
||||
* files can be processed effectively if there aren't too many polygons. But
|
||||
* extremely noisy rasters with many one pixel polygons will end up being
|
||||
* expensive (in memory) to process.
|
||||
*
|
||||
* @param hSrcBand the source raster band to be processed.
|
||||
* @param hMaskBand an optional mask band. All pixels in the mask band with a
|
||||
* value other than zero will be considered suitable for inclusion in polygons.
|
||||
* @param hDstBand the output raster band. It may be the same as hSrcBand
|
||||
* to update the source in place.
|
||||
* @param nSizeThreshold raster polygons with sizes smaller than this will
|
||||
* be merged into their largest neighbour.
|
||||
* @param nConnectedness either 4 indicating that diagonal pixels are not
|
||||
* considered directly adjacent for polygon membership purposes or 8
|
||||
* indicating they are.
|
||||
* @param papszOptions algorithm options in name=value list form. None currently
|
||||
* supported.
|
||||
* @param pfnProgress callback for reporting algorithm progress matching the
|
||||
* GDALProgressFunc() semantics. May be NULL.
|
||||
* @param pProgressArg callback argument passed to pfnProgress.
|
||||
*
|
||||
* @return CE_None on success or CE_Failure if an error occurs.
|
||||
*/
|
||||
|
||||
CPLErr CPL_STDCALL
|
||||
GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
|
||||
GDALRasterBandH hDstBand,
|
||||
int nSizeThreshold, int nConnectedness,
|
||||
CPL_UNUSED char **papszOptions,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg )
|
||||
{
|
||||
VALIDATE_POINTER1( hSrcBand, "GDALSieveFilter", CE_Failure );
|
||||
VALIDATE_POINTER1( hDstBand, "GDALSieveFilter", CE_Failure );
|
||||
|
||||
if( pfnProgress == NULL )
|
||||
pfnProgress = GDALDummyProgress;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Allocate working buffers. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLErr eErr = CE_None;
|
||||
int nXSize = GDALGetRasterBandXSize( hSrcBand );
|
||||
int nYSize = GDALGetRasterBandYSize( hSrcBand );
|
||||
GInt32 *panLastLineVal = (GInt32 *) VSIMalloc2(sizeof(GInt32), nXSize);
|
||||
GInt32 *panThisLineVal = (GInt32 *) VSIMalloc2(sizeof(GInt32), nXSize);
|
||||
GInt32 *panLastLineId = (GInt32 *) VSIMalloc2(sizeof(GInt32), nXSize);
|
||||
GInt32 *panThisLineId = (GInt32 *) VSIMalloc2(sizeof(GInt32), nXSize);
|
||||
GInt32 *panThisLineWriteVal = (GInt32 *) VSIMalloc2(sizeof(GInt32), nXSize);
|
||||
GByte *pabyMaskLine = (hMaskBand != NULL) ? (GByte *) VSIMalloc(nXSize) : NULL;
|
||||
if (panLastLineVal == NULL || panThisLineVal == NULL ||
|
||||
panLastLineId == NULL || panThisLineId == NULL ||
|
||||
panThisLineWriteVal == NULL ||
|
||||
(hMaskBand != NULL && pabyMaskLine == NULL))
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_OutOfMemory,
|
||||
"Could not allocate enough memory for temporary buffers");
|
||||
CPLFree( panThisLineId );
|
||||
CPLFree( panLastLineId );
|
||||
CPLFree( panThisLineVal );
|
||||
CPLFree( panLastLineVal );
|
||||
CPLFree( panThisLineWriteVal );
|
||||
CPLFree( pabyMaskLine );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* The first pass over the raster is only used to build up the */
|
||||
/* polygon id map so we will know in advance what polygons are */
|
||||
/* what on the second pass. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int iY, iX, iPoly;
|
||||
GDALRasterPolygonEnumerator oFirstEnum( nConnectedness );
|
||||
std::vector<int> anPolySizes;
|
||||
|
||||
for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
|
||||
{
|
||||
eErr = GDALRasterIO(
|
||||
hSrcBand,
|
||||
GF_Read, 0, iY, nXSize, 1,
|
||||
panThisLineVal, nXSize, 1, GDT_Int32, 0, 0 );
|
||||
|
||||
if( eErr == CE_None && hMaskBand != NULL )
|
||||
eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize, panThisLineVal );
|
||||
|
||||
if( iY == 0 )
|
||||
oFirstEnum.ProcessLine(
|
||||
NULL, panThisLineVal, NULL, panThisLineId, nXSize );
|
||||
else
|
||||
oFirstEnum.ProcessLine(
|
||||
panLastLineVal, panThisLineVal,
|
||||
panLastLineId, panThisLineId,
|
||||
nXSize );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Accumulate polygon sizes. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( oFirstEnum.nNextPolygonId > (int) anPolySizes.size() )
|
||||
anPolySizes.resize( oFirstEnum.nNextPolygonId );
|
||||
|
||||
for( iX = 0; iX < nXSize; iX++ )
|
||||
{
|
||||
iPoly = panThisLineId[iX];
|
||||
|
||||
CPLAssert( iPoly >= 0 );
|
||||
if( anPolySizes[iPoly] < MY_MAX_INT )
|
||||
anPolySizes[iPoly] += 1;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* swap this/last lines. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GInt32 *panTmp = panLastLineVal;
|
||||
panLastLineVal = panThisLineVal;
|
||||
panThisLineVal = panTmp;
|
||||
|
||||
panTmp = panThisLineId;
|
||||
panThisLineId = panLastLineId;
|
||||
panLastLineId = panTmp;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Report progress, and support interrupts. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( eErr == CE_None
|
||||
&& !pfnProgress( 0.25 * ((iY+1) / (double) nYSize),
|
||||
"", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
eErr = CE_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Make a pass through the maps, ensuring every polygon id */
|
||||
/* points to the final id it should use, not an intermediate */
|
||||
/* value. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
oFirstEnum.CompleteMerges();
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Push the sizes of merged polygon fragments into the the */
|
||||
/* merged polygon id's count. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( iPoly = 0; iPoly < oFirstEnum.nNextPolygonId; iPoly++ )
|
||||
{
|
||||
if( oFirstEnum.panPolyIdMap[iPoly] != iPoly )
|
||||
{
|
||||
GIntBig nSize = anPolySizes[oFirstEnum.panPolyIdMap[iPoly]];
|
||||
|
||||
nSize += anPolySizes[iPoly];
|
||||
|
||||
if( nSize > MY_MAX_INT )
|
||||
nSize = MY_MAX_INT;
|
||||
|
||||
anPolySizes[oFirstEnum.panPolyIdMap[iPoly]] = (int)nSize;
|
||||
anPolySizes[iPoly] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* We will use a new enumerator for the second pass primariliy */
|
||||
/* so we can preserve the first pass map. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GDALRasterPolygonEnumerator oSecondEnum( nConnectedness );
|
||||
|
||||
std::vector<int> anBigNeighbour;
|
||||
anBigNeighbour.resize( anPolySizes.size() );
|
||||
|
||||
for( iPoly = 0; iPoly < (int) anPolySizes.size(); iPoly++ )
|
||||
anBigNeighbour[iPoly] = -1;
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Second pass ... identify the largest neighbour for each */
|
||||
/* polygon. */
|
||||
/* ==================================================================== */
|
||||
for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
|
||||
{
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read the image data. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1,
|
||||
panThisLineVal, nXSize, 1, GDT_Int32, 0, 0 );
|
||||
|
||||
if( eErr == CE_None && hMaskBand != NULL )
|
||||
eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize, panThisLineVal );
|
||||
|
||||
if( eErr != CE_None )
|
||||
continue;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Determine what polygon the various pixels belong to (redoing */
|
||||
/* the same thing done in the first pass above). */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( iY == 0 )
|
||||
oSecondEnum.ProcessLine(
|
||||
NULL, panThisLineVal, NULL, panThisLineId, nXSize );
|
||||
else
|
||||
oSecondEnum.ProcessLine(
|
||||
panLastLineVal, panThisLineVal,
|
||||
panLastLineId, panThisLineId,
|
||||
nXSize );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Check our neighbours, and update our biggest neighbour map */
|
||||
/* as appropriate. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( iX = 0; iX < nXSize; iX++ )
|
||||
{
|
||||
if( iY > 0 )
|
||||
{
|
||||
CompareNeighbour( panThisLineId[iX],
|
||||
panLastLineId[iX],
|
||||
oFirstEnum.panPolyIdMap,
|
||||
oFirstEnum.panPolyValue,
|
||||
anPolySizes, anBigNeighbour );
|
||||
|
||||
if( iX > 0 && nConnectedness == 8 )
|
||||
CompareNeighbour( panThisLineId[iX],
|
||||
panLastLineId[iX-1],
|
||||
oFirstEnum.panPolyIdMap,
|
||||
oFirstEnum.panPolyValue,
|
||||
anPolySizes, anBigNeighbour );
|
||||
|
||||
if( iX < nXSize-1 && nConnectedness == 8 )
|
||||
CompareNeighbour( panThisLineId[iX],
|
||||
panLastLineId[iX+1],
|
||||
oFirstEnum.panPolyIdMap,
|
||||
oFirstEnum.panPolyValue,
|
||||
anPolySizes, anBigNeighbour );
|
||||
|
||||
}
|
||||
|
||||
if( iX > 0 )
|
||||
CompareNeighbour( panThisLineId[iX],
|
||||
panThisLineId[iX-1],
|
||||
oFirstEnum.panPolyIdMap,
|
||||
oFirstEnum.panPolyValue,
|
||||
anPolySizes, anBigNeighbour );
|
||||
|
||||
// We don't need to compare to next pixel or next line
|
||||
// since they will be compared to us.
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Swap pixel value, and polygon id lines to be ready for the */
|
||||
/* next line. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GInt32 *panTmp = panLastLineVal;
|
||||
panLastLineVal = panThisLineVal;
|
||||
panThisLineVal = panTmp;
|
||||
|
||||
panTmp = panThisLineId;
|
||||
panThisLineId = panLastLineId;
|
||||
panLastLineId = panTmp;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Report progress, and support interrupts. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( eErr == CE_None
|
||||
&& !pfnProgress( 0.25 + 0.25 * ((iY+1) / (double) nYSize),
|
||||
"", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
eErr = CE_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* If our biggest neighbour is still smaller than the */
|
||||
/* threshold, then try tracking to that polygons biggest */
|
||||
/* neighbour, and so forth. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int nFailedMerges = 0;
|
||||
int nIsolatedSmall = 0;
|
||||
int nSieveTargets = 0;
|
||||
|
||||
for( iPoly = 0; iPoly < (int) anPolySizes.size(); iPoly++ )
|
||||
{
|
||||
if( oFirstEnum.panPolyIdMap[iPoly] != iPoly )
|
||||
continue;
|
||||
|
||||
// Ignore nodata polygons.
|
||||
if( oFirstEnum.panPolyValue[iPoly] == GP_NODATA_MARKER )
|
||||
continue;
|
||||
|
||||
// Don't try to merge polygons larger than the threshold.
|
||||
if( anPolySizes[iPoly] >= nSizeThreshold )
|
||||
{
|
||||
anBigNeighbour[iPoly] = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
nSieveTargets++;
|
||||
|
||||
// if we have no neighbours but we are small, what shall we do?
|
||||
if( anBigNeighbour[iPoly] == -1 )
|
||||
{
|
||||
nIsolatedSmall++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If our biggest neighbour is larger than the threshold
|
||||
// then we are golden.
|
||||
if( anPolySizes[anBigNeighbour[iPoly]] >= nSizeThreshold )
|
||||
continue;
|
||||
|
||||
#ifdef notdef
|
||||
// Will our neighbours biggest neighbour do?
|
||||
// Eventually we need something sort of recursive here with
|
||||
// loop detection.
|
||||
if( anPolySizes[anBigNeighbour[anBigNeighbour[iPoly]]]
|
||||
>= nSizeThreshold )
|
||||
{
|
||||
anBigNeighbour[iPoly] = anBigNeighbour[anBigNeighbour[iPoly]];
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
nFailedMerges++;
|
||||
anBigNeighbour[iPoly] = -1;
|
||||
}
|
||||
|
||||
CPLDebug( "GDALSieveFilter",
|
||||
"Small Polygons: %d, Isolated: %d, Unmergable: %d",
|
||||
nSieveTargets, nIsolatedSmall, nFailedMerges );
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Make a third pass over the image, actually applying the */
|
||||
/* merges. We reuse the second enumerator but preserve the */
|
||||
/* "final maps" from the first. */
|
||||
/* ==================================================================== */
|
||||
oSecondEnum.Clear();
|
||||
|
||||
|
||||
for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
|
||||
{
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read the image data. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1,
|
||||
panThisLineVal, nXSize, 1, GDT_Int32, 0, 0 );
|
||||
|
||||
memcpy( panThisLineWriteVal, panThisLineVal, 4 * nXSize );
|
||||
|
||||
if( eErr == CE_None && hMaskBand != NULL )
|
||||
eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize, panThisLineVal );
|
||||
|
||||
if( eErr != CE_None )
|
||||
continue;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Determine what polygon the various pixels belong to (redoing */
|
||||
/* the same thing done in the first pass above). */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( iY == 0 )
|
||||
oSecondEnum.ProcessLine(
|
||||
NULL, panThisLineVal, NULL, panThisLineId, nXSize );
|
||||
else
|
||||
oSecondEnum.ProcessLine(
|
||||
panLastLineVal, panThisLineVal,
|
||||
panLastLineId, panThisLineId,
|
||||
nXSize );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Reprocess the actual pixel values according to the polygon */
|
||||
/* merging, and write out this line of image data. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( iX = 0; iX < nXSize; iX++ )
|
||||
{
|
||||
int iThisPoly = oFirstEnum.panPolyIdMap[panThisLineId[iX]];
|
||||
|
||||
if( anBigNeighbour[iThisPoly] != -1 )
|
||||
{
|
||||
panThisLineWriteVal[iX] =
|
||||
oFirstEnum.panPolyValue[
|
||||
anBigNeighbour[iThisPoly]];
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Write the update data out. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
eErr = GDALRasterIO( hDstBand, GF_Write, 0, iY, nXSize, 1,
|
||||
panThisLineWriteVal, nXSize, 1, GDT_Int32, 0, 0 );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Swap pixel value, and polygon id lines to be ready for the */
|
||||
/* next line. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GInt32 *panTmp = panLastLineVal;
|
||||
panLastLineVal = panThisLineVal;
|
||||
panThisLineVal = panTmp;
|
||||
|
||||
panTmp = panThisLineId;
|
||||
panThisLineId = panLastLineId;
|
||||
panLastLineId = panTmp;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Report progress, and support interrupts. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( eErr == CE_None
|
||||
&& !pfnProgress( 0.5 + 0.5 * ((iY+1) / (double) nYSize),
|
||||
"", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
eErr = CE_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Cleanup */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLFree( panThisLineId );
|
||||
CPLFree( panLastLineId );
|
||||
CPLFree( panThisLineVal );
|
||||
CPLFree( panLastLineVal );
|
||||
CPLFree( panThisLineWriteVal );
|
||||
CPLFree( pabyMaskLine );
|
||||
|
||||
return eErr;
|
||||
}
|
||||
446
bazaar/plugin/gdal/alg/gdalsimplewarp.cpp
Normal file
446
bazaar/plugin/gdal/alg/gdalsimplewarp.cpp
Normal file
|
|
@ -0,0 +1,446 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdalsimplewarp.cpp 15436 2008-09-24 19:26:31Z rouault $
|
||||
*
|
||||
* Project: Mapinfo Image Warper
|
||||
* Purpose: Simple (source in memory) warp algorithm.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2002, i3 - information integration and imaging, Fort Collin,CO
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_priv.h"
|
||||
#include "gdal_alg.h"
|
||||
#include "cpl_string.h"
|
||||
|
||||
CPL_CVSID("$Id: gdalsimplewarp.cpp 15436 2008-09-24 19:26:31Z rouault $");
|
||||
|
||||
static void
|
||||
GDALSimpleWarpRemapping( int nBandCount, GByte **papabySrcData,
|
||||
int nSrcXSize, int nSrcYSize,
|
||||
char **papszWarpOptions );
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALSimpleImageWarp() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Perform simple image warp.
|
||||
*
|
||||
* Copies an image from a source dataset to a destination dataset applying
|
||||
* an application defined transformation. This algorithm is called simple
|
||||
* because it lacks many options such as resampling kernels (other than
|
||||
* nearest neighbour), support for data types other than 8bit, and the
|
||||
* ability to warp images without holding the entire source and destination
|
||||
* image in memory.
|
||||
*
|
||||
* The following option(s) may be passed in papszWarpOptions.
|
||||
* <ul>
|
||||
* <li> "INIT=v[,v...]": This option indicates that the output dataset should
|
||||
* be initialized to the indicated value in any area valid data is not written.
|
||||
* Distinct values may be listed for each band separated by columns.
|
||||
* </ul>
|
||||
*
|
||||
* @param hSrcDS the source image dataset.
|
||||
* @param hDstDS the destination image dataset.
|
||||
* @param nBandCount the number of bands to be warped. If zero, all bands
|
||||
* will be processed.
|
||||
* @param panBandList the list of bands to translate.
|
||||
* @param pfnTransform the transformation function to call. See
|
||||
* GDALTransformerFunc().
|
||||
* @param pTransformArg the callback handle to pass to pfnTransform.
|
||||
* @param pfnProgress the function used to report progress. See
|
||||
* GDALProgressFunc().
|
||||
* @param pProgressArg the callback handle to pass to pfnProgress.
|
||||
* @param papszWarpOptions additional options controlling the warp.
|
||||
*
|
||||
* @return TRUE if the operation completes, or FALSE if an error occurs.
|
||||
*/
|
||||
|
||||
int CPL_STDCALL
|
||||
GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
|
||||
int nBandCount, int *panBandList,
|
||||
GDALTransformerFunc pfnTransform, void *pTransformArg,
|
||||
GDALProgressFunc pfnProgress, void *pProgressArg,
|
||||
char **papszWarpOptions )
|
||||
|
||||
{
|
||||
VALIDATE_POINTER1( hSrcDS, "GDALSimpleImageWarp", 0 );
|
||||
VALIDATE_POINTER1( hDstDS, "GDALSimpleImageWarp", 0 );
|
||||
|
||||
int iBand, bCancelled = FALSE;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* If no bands provided assume we should process all bands. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( nBandCount == 0 )
|
||||
{
|
||||
int nResult;
|
||||
|
||||
nBandCount = GDALGetRasterCount( hSrcDS );
|
||||
if (nBandCount == 0)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"No raster band in source dataset");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
panBandList = (int *) CPLCalloc(sizeof(int),nBandCount);
|
||||
|
||||
for( iBand = 0; iBand < nBandCount; iBand++ )
|
||||
panBandList[iBand] = iBand+1;
|
||||
|
||||
nResult = GDALSimpleImageWarp( hSrcDS, hDstDS, nBandCount, panBandList,
|
||||
pfnTransform, pTransformArg,
|
||||
pfnProgress, pProgressArg,
|
||||
papszWarpOptions );
|
||||
CPLFree( panBandList );
|
||||
return nResult;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Post initial progress. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( pfnProgress )
|
||||
{
|
||||
if( !pfnProgress( 0.0, "", pProgressArg ) )
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Load the source image band(s). */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int nSrcXSize = GDALGetRasterXSize(hSrcDS);
|
||||
int nSrcYSize = GDALGetRasterYSize(hSrcDS);
|
||||
GByte **papabySrcData;
|
||||
|
||||
papabySrcData = (GByte **) CPLCalloc(nBandCount,sizeof(GByte*));
|
||||
for( iBand = 0; iBand < nBandCount; iBand++ )
|
||||
{
|
||||
papabySrcData[iBand] = (GByte *) VSIMalloc(nSrcXSize*nSrcYSize);
|
||||
|
||||
GDALRasterIO( GDALGetRasterBand(hSrcDS,panBandList[iBand]), GF_Read,
|
||||
0, 0, nSrcXSize, nSrcYSize,
|
||||
papabySrcData[iBand], nSrcXSize, nSrcYSize, GDT_Byte,
|
||||
0, 0 );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Check for remap request(s). */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GDALSimpleWarpRemapping( nBandCount, papabySrcData, nSrcXSize, nSrcYSize,
|
||||
papszWarpOptions );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Allocate scanline buffers for output image. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int nDstXSize = GDALGetRasterXSize( hDstDS );
|
||||
int nDstYSize = GDALGetRasterYSize( hDstDS );
|
||||
GByte **papabyDstLine;
|
||||
|
||||
papabyDstLine = (GByte **) CPLCalloc(nBandCount,sizeof(GByte*));
|
||||
|
||||
for( iBand = 0; iBand < nBandCount; iBand++ )
|
||||
papabyDstLine[iBand] = (GByte *) CPLMalloc( nDstXSize );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Allocate x,y,z coordinate arrays for transformation ... one */
|
||||
/* scanlines worth of positions. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
double *padfX, *padfY, *padfZ;
|
||||
int *pabSuccess;
|
||||
|
||||
padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
|
||||
padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
|
||||
padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
|
||||
pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Establish the value we will use to initialize the bands. We */
|
||||
/* default to -1 indicating the initial value should be read */
|
||||
/* and preserved from the source file, but allow this to be */
|
||||
/* overridden by passed */
|
||||
/* option(s). */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int *panBandInit;
|
||||
|
||||
panBandInit = (int *) CPLCalloc(sizeof(int),nBandCount);
|
||||
if( CSLFetchNameValue( papszWarpOptions, "INIT" ) )
|
||||
{
|
||||
int iBand, nTokenCount;
|
||||
char **papszTokens =
|
||||
CSLTokenizeStringComplex( CSLFetchNameValue( papszWarpOptions,
|
||||
"INIT" ),
|
||||
" ,", FALSE, FALSE );
|
||||
|
||||
nTokenCount = CSLCount(papszTokens);
|
||||
|
||||
for( iBand = 0; iBand < nBandCount; iBand++ )
|
||||
{
|
||||
if( nTokenCount == 0 )
|
||||
panBandInit[iBand] = 0;
|
||||
else
|
||||
panBandInit[iBand] =
|
||||
atoi(papszTokens[MIN(iBand,nTokenCount-1)]);
|
||||
}
|
||||
|
||||
CSLDestroy(papszTokens);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Loop over all the scanlines in the output image. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int iDstY;
|
||||
|
||||
for( iDstY = 0; iDstY < nDstYSize; iDstY++ )
|
||||
{
|
||||
int iDstX;
|
||||
|
||||
// Clear output buffer to "transparent" value. Shouldn't we
|
||||
// really be reading from the destination file to support overlay?
|
||||
for( iBand = 0; iBand < nBandCount; iBand++ )
|
||||
{
|
||||
if( panBandInit[iBand] == -1 )
|
||||
GDALRasterIO( GDALGetRasterBand(hDstDS,iBand+1), GF_Read,
|
||||
0, iDstY, nDstXSize, 1,
|
||||
papabyDstLine[iBand], nDstXSize, 1, GDT_Byte,
|
||||
0, 0 );
|
||||
else
|
||||
memset( papabyDstLine[iBand], panBandInit[iBand], nDstXSize );
|
||||
}
|
||||
|
||||
// Set point to transform.
|
||||
for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
|
||||
{
|
||||
padfX[iDstX] = iDstX + 0.5;
|
||||
padfY[iDstX] = iDstY + 0.5;
|
||||
padfZ[iDstX] = 0.0;
|
||||
}
|
||||
|
||||
// Transform the points from destination pixel/line coordinates
|
||||
// to source pixel/line coordinates.
|
||||
pfnTransform( pTransformArg, TRUE, nDstXSize,
|
||||
padfX, padfY, padfZ, pabSuccess );
|
||||
|
||||
// Loop over the output scanline.
|
||||
for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
|
||||
{
|
||||
if( !pabSuccess[iDstX] )
|
||||
continue;
|
||||
|
||||
// We test against the value before casting to avoid the
|
||||
// problem of asymmetric truncation effects around zero. That is
|
||||
// -0.5 will be 0 when cast to an int.
|
||||
if( padfX[iDstX] < 0.0 || padfY[iDstX] < 0.0 )
|
||||
continue;
|
||||
|
||||
int iSrcX, iSrcY, iSrcOffset;
|
||||
|
||||
iSrcX = (int) padfX[iDstX];
|
||||
iSrcY = (int) padfY[iDstX];
|
||||
|
||||
if( iSrcX >= nSrcXSize || iSrcY >= nSrcYSize )
|
||||
continue;
|
||||
|
||||
iSrcOffset = iSrcX + iSrcY * nSrcXSize;
|
||||
|
||||
for( iBand = 0; iBand < nBandCount; iBand++ )
|
||||
papabyDstLine[iBand][iDstX] = papabySrcData[iBand][iSrcOffset];
|
||||
}
|
||||
|
||||
// Write scanline to disk.
|
||||
for( iBand = 0; iBand < nBandCount; iBand++ )
|
||||
{
|
||||
GDALRasterIO( GDALGetRasterBand(hDstDS,iBand+1), GF_Write,
|
||||
0, iDstY, nDstXSize, 1,
|
||||
papabyDstLine[iBand], nDstXSize, 1, GDT_Byte, 0, 0 );
|
||||
}
|
||||
|
||||
if( pfnProgress != NULL )
|
||||
{
|
||||
if( !pfnProgress( (iDstY+1) / (double) nDstYSize,
|
||||
"", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
bCancelled = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Cleanup working buffers. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( iBand = 0; iBand < nBandCount; iBand++ )
|
||||
{
|
||||
CPLFree( papabyDstLine[iBand] );
|
||||
CPLFree( papabySrcData[iBand] );
|
||||
}
|
||||
|
||||
CPLFree( panBandInit );
|
||||
CPLFree( papabyDstLine );
|
||||
CPLFree( papabySrcData );
|
||||
CPLFree( padfX );
|
||||
CPLFree( padfY );
|
||||
CPLFree( padfZ );
|
||||
CPLFree( pabSuccess );
|
||||
|
||||
return !bCancelled;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALSimpleWarpRemapping() */
|
||||
/* */
|
||||
/* This function implements any raster remapping requested in */
|
||||
/* the options list. The remappings are applied to the source */
|
||||
/* data before warping. Two kinds are support ... REMAP */
|
||||
/* commands which remap selected pixel values for any band and */
|
||||
/* REMAP_MULTI which only remap pixels matching the input in */
|
||||
/* all bands at once (ie. to remap an RGB value to another). */
|
||||
/************************************************************************/
|
||||
|
||||
static void
|
||||
GDALSimpleWarpRemapping( int nBandCount, GByte **papabySrcData,
|
||||
int nSrcXSize, int nSrcYSize,
|
||||
char **papszWarpOptions )
|
||||
|
||||
{
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Process any and all single value REMAP commands. */
|
||||
/* ==================================================================== */
|
||||
int iRemap;
|
||||
char **papszRemaps = CSLFetchNameValueMultiple( papszWarpOptions,
|
||||
"REMAP" );
|
||||
|
||||
for( iRemap = 0; iRemap < CSLCount(papszRemaps); iRemap++ )
|
||||
{
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* What are the pixel values to map from and to? */
|
||||
/* -------------------------------------------------------------------- */
|
||||
char **papszTokens = CSLTokenizeString( papszRemaps[iRemap] );
|
||||
int nFromValue, nToValue;
|
||||
|
||||
if( CSLCount(papszTokens) != 2 )
|
||||
{
|
||||
CPLError( CE_Warning, CPLE_AppDefined,
|
||||
"Ill formed REMAP `%s' ignored in GDALSimpleWarpRemapping()",
|
||||
papszRemaps[iRemap] );
|
||||
continue;
|
||||
}
|
||||
|
||||
nFromValue = atoi(papszTokens[0]);
|
||||
nToValue = atoi(papszTokens[1]);
|
||||
|
||||
CSLDestroy( papszTokens );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Pass over each band searching for matches. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( int iBand = 0; iBand < nBandCount; iBand++ )
|
||||
{
|
||||
GByte *pabyData = papabySrcData[iBand];
|
||||
int nPixelCount = nSrcXSize * nSrcYSize;
|
||||
|
||||
while( nPixelCount != 0 )
|
||||
{
|
||||
if( *pabyData == nFromValue )
|
||||
*pabyData = (GByte) nToValue;
|
||||
|
||||
pabyData++;
|
||||
nPixelCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CSLDestroy( papszRemaps );
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Process any and all REMAP_MULTI commands. */
|
||||
/* ==================================================================== */
|
||||
papszRemaps = CSLFetchNameValueMultiple( papszWarpOptions,
|
||||
"REMAP_MULTI" );
|
||||
|
||||
for( iRemap = 0; iRemap < CSLCount(papszRemaps); iRemap++ )
|
||||
{
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* What are the pixel values to map from and to? */
|
||||
/* -------------------------------------------------------------------- */
|
||||
char **papszTokens = CSLTokenizeString( papszRemaps[iRemap] );
|
||||
int *panFromValue, *panToValue;
|
||||
int nMapBandCount, iBand;
|
||||
|
||||
if( CSLCount(papszTokens) % 2 == 1
|
||||
|| CSLCount(papszTokens) == 0
|
||||
|| CSLCount(papszTokens) > nBandCount * 2 )
|
||||
{
|
||||
CPLError( CE_Warning, CPLE_AppDefined,
|
||||
"Ill formed REMAP_MULTI `%s' ignored in GDALSimpleWarpRemapping()",
|
||||
papszRemaps[iRemap] );
|
||||
continue;
|
||||
}
|
||||
|
||||
nMapBandCount = CSLCount(papszTokens) / 2;
|
||||
|
||||
panFromValue = (int *) CPLMalloc(sizeof(int) * nMapBandCount );
|
||||
panToValue = (int *) CPLMalloc(sizeof(int) * nMapBandCount );
|
||||
|
||||
for( iBand = 0; iBand < nMapBandCount; iBand++ )
|
||||
{
|
||||
panFromValue[iBand] = atoi(papszTokens[iBand]);
|
||||
panToValue[iBand] = atoi(papszTokens[iBand+nMapBandCount]);
|
||||
}
|
||||
|
||||
CSLDestroy( papszTokens );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Search for matching values to replace. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int nPixelCount = nSrcXSize * nSrcYSize;
|
||||
int iPixel;
|
||||
|
||||
for( iPixel = 0; iPixel < nPixelCount; iPixel++ )
|
||||
{
|
||||
if( papabySrcData[0][iPixel] != panFromValue[0] )
|
||||
continue;
|
||||
|
||||
int bMatch = TRUE;
|
||||
|
||||
for( iBand = 1; iBand < nMapBandCount; iBand++ )
|
||||
{
|
||||
if( papabySrcData[iBand][iPixel] != panFromValue[iBand] )
|
||||
bMatch = FALSE;
|
||||
}
|
||||
|
||||
if( !bMatch )
|
||||
continue;
|
||||
|
||||
for( iBand = 0; iBand < nMapBandCount; iBand++ )
|
||||
papabySrcData[iBand][iPixel] = (GByte) panToValue[iBand];
|
||||
}
|
||||
|
||||
CPLFree( panFromValue );
|
||||
CPLFree( panToValue );
|
||||
}
|
||||
|
||||
CSLDestroy( papszRemaps );
|
||||
}
|
||||
3508
bazaar/plugin/gdal/alg/gdaltransformer.cpp
Normal file
3508
bazaar/plugin/gdal/alg/gdaltransformer.cpp
Normal file
File diff suppressed because it is too large
Load diff
151
bazaar/plugin/gdal/alg/gdaltransformgeolocs.cpp
Normal file
151
bazaar/plugin/gdal/alg/gdaltransformgeolocs.cpp
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
/******************************************************************************
|
||||
* $Id$
|
||||
*
|
||||
* Project: GDAL
|
||||
* Purpose: Algorithm to apply a transformer to geolocation style bands.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2012, Frank Warmerdam
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_alg_priv.h"
|
||||
#include "gdal_priv.h"
|
||||
#include "cpl_conv.h"
|
||||
|
||||
CPL_CVSID("$Id$");
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALTransformGeolocations() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Transform locations held in bands.
|
||||
*
|
||||
* The X/Y and possibly Z values in the identified bands are transformed
|
||||
* using a spatial transformer. The changes values are written back to the
|
||||
* source bands so they need to updatable.
|
||||
*
|
||||
* @param hXBand the band containing the X locations (usually long/easting).
|
||||
* @param hYBand the band containing the Y locations (usually lat/northing).
|
||||
* @param hZBand the band containing the Z locations (may be NULL).
|
||||
* @param pfnTransformer the transformer function.
|
||||
* @param pTransformArg the callback data for the transformer function.
|
||||
* @param pfnProgress callback for reporting algorithm progress matching the
|
||||
* GDALProgressFunc() semantics. May be NULL.
|
||||
* @param pProgressArg callback argument passed to pfnProgress.
|
||||
* @param papszOptions list of name/value options - none currently supported.
|
||||
*
|
||||
* @return CE_None on success or CE_Failure if an error occurs.
|
||||
*/
|
||||
|
||||
CPLErr
|
||||
GDALTransformGeolocations( GDALRasterBandH hXBand,
|
||||
GDALRasterBandH hYBand,
|
||||
GDALRasterBandH hZBand,
|
||||
GDALTransformerFunc pfnTransformer,
|
||||
void *pTransformArg,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void *pProgressArg,
|
||||
CPL_UNUSED char **papszOptions )
|
||||
|
||||
{
|
||||
VALIDATE_POINTER1( hXBand, "GDALTransformGeolocations", CE_Failure );
|
||||
VALIDATE_POINTER1( hYBand, "GDALTransformGeolocations", CE_Failure );
|
||||
|
||||
if( pfnProgress == NULL )
|
||||
pfnProgress = GDALDummyProgress;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Ensure the bands are matching in size. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GDALRasterBand *poXBand = (GDALRasterBand *) hXBand;
|
||||
GDALRasterBand *poYBand = (GDALRasterBand *) hYBand;
|
||||
GDALRasterBand *poZBand = (GDALRasterBand *) hZBand;
|
||||
int nXSize = poXBand->GetXSize();
|
||||
int nYSize = poXBand->GetYSize();
|
||||
|
||||
if( nXSize != poYBand->GetXSize()
|
||||
|| nYSize != poYBand->GetYSize()
|
||||
|| (poZBand != NULL && nXSize != poZBand->GetXSize())
|
||||
|| (poZBand != NULL && nYSize != poZBand->GetYSize()) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Size of X, Y and/or Z bands do not match." );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Allocate a buffer large enough to hold one whole row. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
double *padfX = (double*) CPLMalloc(sizeof(double) * nXSize);
|
||||
double *padfY = (double*) CPLMalloc(sizeof(double) * nXSize);
|
||||
double *padfZ = (double*) CPLMalloc(sizeof(double) * nXSize);
|
||||
int *panSuccess = (int*) CPLMalloc(sizeof(int) * nXSize);
|
||||
int iLine;
|
||||
CPLErr eErr = CE_None;
|
||||
|
||||
pfnProgress( 0.0, "", pProgressArg );
|
||||
for( iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ )
|
||||
{
|
||||
eErr = poXBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
|
||||
padfX, nXSize, 1, GDT_Float64, 0, 0, NULL );
|
||||
if( eErr == CE_None )
|
||||
eErr = poYBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
|
||||
padfY, nXSize, 1, GDT_Float64, 0, 0, NULL );
|
||||
if( eErr == CE_None && poZBand != NULL )
|
||||
eErr = poZBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
|
||||
padfZ, nXSize, 1, GDT_Float64, 0, 0, NULL );
|
||||
else
|
||||
memset( padfZ, 0, sizeof(double) * nXSize);
|
||||
|
||||
if( eErr == CE_None )
|
||||
{
|
||||
pfnTransformer( pTransformArg, FALSE, nXSize,
|
||||
padfX, padfY, padfZ, panSuccess );
|
||||
}
|
||||
|
||||
if( eErr == CE_None )
|
||||
eErr = poXBand->RasterIO( GF_Write, 0, iLine, nXSize, 1,
|
||||
padfX, nXSize, 1, GDT_Float64, 0, 0, NULL );
|
||||
if( eErr == CE_None )
|
||||
eErr = poYBand->RasterIO( GF_Write, 0, iLine, nXSize, 1,
|
||||
padfY, nXSize, 1, GDT_Float64, 0, 0, NULL );
|
||||
if( eErr == CE_None && poZBand != NULL )
|
||||
eErr = poZBand->RasterIO( GF_Write, 0, iLine, nXSize, 1,
|
||||
padfZ, nXSize, 1, GDT_Float64, 0, 0, NULL );
|
||||
|
||||
if( eErr == CE_None )
|
||||
pfnProgress( (iLine+1) / (double) nYSize, "", pProgressArg );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Cleanup */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLFree( padfX );
|
||||
CPLFree( padfY );
|
||||
CPLFree( padfZ );
|
||||
CPLFree( panSuccess );
|
||||
|
||||
return eErr;
|
||||
}
|
||||
1549
bazaar/plugin/gdal/alg/gdalwarper.cpp
Normal file
1549
bazaar/plugin/gdal/alg/gdalwarper.cpp
Normal file
File diff suppressed because it is too large
Load diff
450
bazaar/plugin/gdal/alg/gdalwarper.h
Normal file
450
bazaar/plugin/gdal/alg/gdalwarper.h
Normal file
|
|
@ -0,0 +1,450 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdalwarper.h 29330 2015-06-14 12:11:11Z rouault $
|
||||
*
|
||||
* Project: GDAL High Performance Warper
|
||||
* Purpose: Prototypes, and definitions for warping related work.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2003, Frank Warmerdam
|
||||
* Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef GDALWARPER_H_INCLUDED
|
||||
#define GDALWARPER_H_INCLUDED
|
||||
|
||||
/**
|
||||
* \file gdalwarper.h
|
||||
*
|
||||
* GDAL warper related entry points and definitions. Eventually it is
|
||||
* expected that this file will be mostly private to the implementation,
|
||||
* and the public C entry points will be available in gdal_alg.h.
|
||||
*/
|
||||
|
||||
#include "gdal_alg.h"
|
||||
#include "cpl_minixml.h"
|
||||
#include "cpl_multiproc.h"
|
||||
|
||||
CPL_C_START
|
||||
|
||||
/* Note: values are selected to be consistent with GDALRIOResampleAlg of gcore/gdal.h */
|
||||
/*! Warp Resampling Algorithm */
|
||||
typedef enum {
|
||||
/*! Nearest neighbour (select on one input pixel) */ GRA_NearestNeighbour=0,
|
||||
/*! Bilinear (2x2 kernel) */ GRA_Bilinear=1,
|
||||
/*! Cubic Convolution Approximation (4x4 kernel) */ GRA_Cubic=2,
|
||||
/*! Cubic B-Spline Approximation (4x4 kernel) */ GRA_CubicSpline=3,
|
||||
/*! Lanczos windowed sinc interpolation (6x6 kernel) */ GRA_Lanczos=4,
|
||||
/*! Average (computes the average of all non-NODATA contributing pixels) */ GRA_Average=5,
|
||||
/*! Mode (selects the value which appears most often of all the sampled points) */ GRA_Mode=6,
|
||||
// GRA_Gauss=7 reserved.
|
||||
/*! Max (selects maximum of all non-NODATA contributing pixels) */ GRA_Max=8,
|
||||
/*! Min (selects minimum of all non-NODATA contributing pixels) */ GRA_Min=9,
|
||||
/*! Med (selects median of all non-NODATA contributing pixels) */ GRA_Med=10,
|
||||
/*! Q1 (selects first quartile of all non-NODATA contributing pixels) */ GRA_Q1=11,
|
||||
/*! Q3 (selects third quartile of all non-NODATA contributing pixels) */ GRA_Q3=12
|
||||
} GDALResampleAlg;
|
||||
|
||||
/*! GWKAverageOrMode Algorithm */
|
||||
typedef enum {
|
||||
/*! Average */ GWKAOM_Average=1,
|
||||
/*! Mode */ GWKAOM_Fmode=2,
|
||||
/*! Mode of GDT_Byte, GDT_UInt16, or GDT_Int16 */ GWKAOM_Imode=3,
|
||||
/*! Maximum */ GWKAOM_Max=4,
|
||||
/*! Minimum */ GWKAOM_Min=5,
|
||||
/*! Quantile */ GWKAOM_Quant=6
|
||||
} GWKAverageOrModeAlg;
|
||||
|
||||
typedef int
|
||||
(*GDALMaskFunc)( void *pMaskFuncArg,
|
||||
int nBandCount, GDALDataType eType,
|
||||
int nXOff, int nYOff,
|
||||
int nXSize, int nYSize,
|
||||
GByte **papabyImageData,
|
||||
int bMaskIsFloat, void *pMask );
|
||||
|
||||
CPLErr CPL_DLL
|
||||
GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
|
||||
int nXOff, int nYOff, int nXSize, int nYSize,
|
||||
GByte **papabyImageData, int bMaskIsFloat,
|
||||
void *pValidityMask, int* pbOutAllValid );
|
||||
|
||||
CPLErr CPL_DLL
|
||||
GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
|
||||
int nXOff, int nYOff, int nXSize, int nYSize,
|
||||
GByte ** /*ppImageData */,
|
||||
int bMaskIsFloat, void *pValidityMask );
|
||||
CPLErr CPL_DLL
|
||||
GDALWarpSrcAlphaMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
|
||||
int nXOff, int nYOff, int nXSize, int nYSize,
|
||||
GByte ** /*ppImageData */,
|
||||
int bMaskIsFloat, void *pValidityMask, int* pbOutAllOpaque );
|
||||
|
||||
CPLErr CPL_DLL
|
||||
GDALWarpSrcMaskMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
|
||||
int nXOff, int nYOff, int nXSize, int nYSize,
|
||||
GByte ** /*ppImageData */,
|
||||
int bMaskIsFloat, void *pValidityMask );
|
||||
|
||||
CPLErr CPL_DLL
|
||||
GDALWarpCutlineMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
|
||||
int nXOff, int nYOff, int nXSize, int nYSize,
|
||||
GByte ** /* ppImageData */,
|
||||
int bMaskIsFloat, void *pValidityMask );
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALWarpOptions */
|
||||
/************************************************************************/
|
||||
|
||||
/** Warp control options for use with GDALWarpOperation::Initialize() */
|
||||
typedef struct {
|
||||
|
||||
char **papszWarpOptions;
|
||||
|
||||
/*! In bytes, 0.0 for internal default */
|
||||
double dfWarpMemoryLimit;
|
||||
|
||||
/*! Resampling algorithm to use */
|
||||
GDALResampleAlg eResampleAlg;
|
||||
|
||||
/*! data type to use during warp operation, GDT_Unknown lets the algorithm
|
||||
select the type */
|
||||
GDALDataType eWorkingDataType;
|
||||
|
||||
/*! Source image dataset. */
|
||||
GDALDatasetH hSrcDS;
|
||||
|
||||
/*! Destination image dataset - may be NULL if only using GDALWarpOperation::WarpRegionToBuffer(). */
|
||||
GDALDatasetH hDstDS;
|
||||
|
||||
/*! Number of bands to process, may be 0 to select all bands. */
|
||||
int nBandCount;
|
||||
|
||||
/*! The band numbers for the source bands to process (1 based) */
|
||||
int *panSrcBands;
|
||||
|
||||
/*! The band numbers for the destination bands to process (1 based) */
|
||||
int *panDstBands;
|
||||
|
||||
/*! The source band so use as an alpha (transparency) value, 0=disabled */
|
||||
int nSrcAlphaBand;
|
||||
|
||||
/*! The dest. band so use as an alpha (transparency) value, 0=disabled */
|
||||
int nDstAlphaBand;
|
||||
|
||||
/*! The "nodata" value real component for each input band, if NULL there isn't one */
|
||||
double *padfSrcNoDataReal;
|
||||
/*! The "nodata" value imaginary component - may be NULL even if real
|
||||
component is provided. */
|
||||
double *padfSrcNoDataImag;
|
||||
|
||||
/*! The "nodata" value real component for each output band, if NULL there isn't one */
|
||||
double *padfDstNoDataReal;
|
||||
/*! The "nodata" value imaginary component - may be NULL even if real
|
||||
component is provided. */
|
||||
double *padfDstNoDataImag;
|
||||
|
||||
/*! GDALProgressFunc() compatible progress reporting function, or NULL
|
||||
if there isn't one. */
|
||||
GDALProgressFunc pfnProgress;
|
||||
|
||||
/*! Callback argument to be passed to pfnProgress. */
|
||||
void *pProgressArg;
|
||||
|
||||
/*! Type of spatial point transformer function */
|
||||
GDALTransformerFunc pfnTransformer;
|
||||
|
||||
/*! Handle to image transformer setup structure */
|
||||
void *pTransformerArg;
|
||||
|
||||
GDALMaskFunc *papfnSrcPerBandValidityMaskFunc;
|
||||
void **papSrcPerBandValidityMaskFuncArg;
|
||||
|
||||
GDALMaskFunc pfnSrcValidityMaskFunc;
|
||||
void *pSrcValidityMaskFuncArg;
|
||||
|
||||
GDALMaskFunc pfnSrcDensityMaskFunc;
|
||||
void *pSrcDensityMaskFuncArg;
|
||||
|
||||
GDALMaskFunc pfnDstDensityMaskFunc;
|
||||
void *pDstDensityMaskFuncArg;
|
||||
|
||||
GDALMaskFunc pfnDstValidityMaskFunc;
|
||||
void *pDstValidityMaskFuncArg;
|
||||
|
||||
CPLErr (*pfnPreWarpChunkProcessor)( void *pKern, void *pArg );
|
||||
void *pPreWarpProcessorArg;
|
||||
|
||||
CPLErr (*pfnPostWarpChunkProcessor)( void *pKern, void *pArg);
|
||||
void *pPostWarpProcessorArg;
|
||||
|
||||
/*! Optional OGRPolygonH for a masking cutline. */
|
||||
void *hCutline;
|
||||
|
||||
/*! Optional blending distance to apply across cutline in pixels, default is zero. */
|
||||
double dfCutlineBlendDist;
|
||||
|
||||
} GDALWarpOptions;
|
||||
|
||||
GDALWarpOptions CPL_DLL * CPL_STDCALL GDALCreateWarpOptions(void);
|
||||
void CPL_DLL CPL_STDCALL GDALDestroyWarpOptions( GDALWarpOptions * );
|
||||
GDALWarpOptions CPL_DLL * CPL_STDCALL
|
||||
GDALCloneWarpOptions( const GDALWarpOptions * );
|
||||
|
||||
CPLXMLNode CPL_DLL * CPL_STDCALL
|
||||
GDALSerializeWarpOptions( const GDALWarpOptions * );
|
||||
GDALWarpOptions CPL_DLL * CPL_STDCALL
|
||||
GDALDeserializeWarpOptions( CPLXMLNode * );
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALReprojectImage() */
|
||||
/************************************************************************/
|
||||
|
||||
CPLErr CPL_DLL CPL_STDCALL
|
||||
GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
|
||||
GDALDatasetH hDstDS, const char *pszDstWKT,
|
||||
GDALResampleAlg eResampleAlg, double dfWarpMemoryLimit,
|
||||
double dfMaxError,
|
||||
GDALProgressFunc pfnProgress, void *pProgressArg,
|
||||
GDALWarpOptions *psOptions );
|
||||
|
||||
CPLErr CPL_DLL CPL_STDCALL
|
||||
GDALCreateAndReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
|
||||
const char *pszDstFilename, const char *pszDstWKT,
|
||||
GDALDriverH hDstDriver, char **papszCreateOptions,
|
||||
GDALResampleAlg eResampleAlg, double dfWarpMemoryLimit,
|
||||
double dfMaxError,
|
||||
GDALProgressFunc pfnProgress, void *pProgressArg,
|
||||
GDALWarpOptions *psOptions );
|
||||
|
||||
/************************************************************************/
|
||||
/* VRTWarpedDataset */
|
||||
/************************************************************************/
|
||||
|
||||
GDALDatasetH CPL_DLL CPL_STDCALL
|
||||
GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
|
||||
const char *pszSrcWKT, const char *pszDstWKT,
|
||||
GDALResampleAlg eResampleAlg,
|
||||
double dfMaxError, const GDALWarpOptions *psOptions );
|
||||
|
||||
GDALDatasetH CPL_DLL CPL_STDCALL
|
||||
GDALCreateWarpedVRT( GDALDatasetH hSrcDS,
|
||||
int nPixels, int nLines, double *padfGeoTransform,
|
||||
GDALWarpOptions *psOptions );
|
||||
|
||||
CPLErr CPL_DLL CPL_STDCALL
|
||||
GDALInitializeWarpedVRT( GDALDatasetH hDS,
|
||||
GDALWarpOptions *psWO );
|
||||
|
||||
CPL_C_END
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALWarpKernel */
|
||||
/* */
|
||||
/* This class represents the lowest level of abstraction. It */
|
||||
/* is holds the imagery for one "chunk" of a warp, and the */
|
||||
/* pre-prepared masks. All IO is done before and after it's */
|
||||
/* operation. This class is not normally used by the */
|
||||
/* application. */
|
||||
/************************************************************************/
|
||||
|
||||
// This is the number of dummy pixels that must be reserved in source arrays
|
||||
// in order to satisfy assumptions made in GWKResample(), and more specifically
|
||||
// by GWKGetPixelRow() that always read a even number of pixels. So if we are
|
||||
// in the situation to read the last pixel of the source array, we need 1 extra
|
||||
// dummy pixel to avoid reading out of bounds.
|
||||
#define WARP_EXTRA_ELTS 1
|
||||
|
||||
class CPL_DLL GDALWarpKernel
|
||||
{
|
||||
public:
|
||||
char **papszWarpOptions;
|
||||
|
||||
GDALResampleAlg eResample;
|
||||
GDALDataType eWorkingDataType;
|
||||
int nBands;
|
||||
|
||||
int nSrcXSize;
|
||||
int nSrcYSize;
|
||||
int nSrcXExtraSize; /* extra pixels (included in nSrcXSize) reserved for filter window. Should be ignored in scale computation */
|
||||
int nSrcYExtraSize; /* extra pixels (included in nSrcYSize) reserved for filter window. Should be ignored in scale computation */
|
||||
GByte **papabySrcImage; /* each subarray must have WARP_EXTRA_ELTS at the end */
|
||||
|
||||
GUInt32 **papanBandSrcValid; /* each subarray must have WARP_EXTRA_ELTS at the end */
|
||||
GUInt32 *panUnifiedSrcValid; /* must have WARP_EXTRA_ELTS at the end */
|
||||
float *pafUnifiedSrcDensity; /* must have WARP_EXTRA_ELTS at the end */
|
||||
|
||||
int nDstXSize;
|
||||
int nDstYSize;
|
||||
GByte **papabyDstImage;
|
||||
GUInt32 *panDstValid;
|
||||
float *pafDstDensity;
|
||||
|
||||
double dfXScale; // Resampling scale, i.e.
|
||||
double dfYScale; // nDstSize/nSrcSize.
|
||||
double dfXFilter; // Size of filter kernel.
|
||||
double dfYFilter;
|
||||
int nXRadius; // Size of window to filter.
|
||||
int nYRadius;
|
||||
int nFiltInitX; // Filtering offset
|
||||
int nFiltInitY;
|
||||
|
||||
int nSrcXOff;
|
||||
int nSrcYOff;
|
||||
|
||||
int nDstXOff;
|
||||
int nDstYOff;
|
||||
|
||||
GDALTransformerFunc pfnTransformer;
|
||||
void *pTransformerArg;
|
||||
|
||||
GDALProgressFunc pfnProgress;
|
||||
void *pProgress;
|
||||
|
||||
double dfProgressBase;
|
||||
double dfProgressScale;
|
||||
|
||||
double *padfDstNoDataReal;
|
||||
|
||||
GDALWarpKernel();
|
||||
virtual ~GDALWarpKernel();
|
||||
|
||||
CPLErr Validate();
|
||||
CPLErr PerformWarp();
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALWarpOperation() */
|
||||
/* */
|
||||
/* This object is application created, or created by a higher */
|
||||
/* level convenience function. It is responsible for */
|
||||
/* subdividing the operation into chunks, loading and saving */
|
||||
/* imagery, and establishing the varios validity and density */
|
||||
/* masks. Actual resampling is done by the GDALWarpKernel. */
|
||||
/************************************************************************/
|
||||
|
||||
typedef struct _GDALWarpChunk GDALWarpChunk;
|
||||
|
||||
class CPL_DLL GDALWarpOperation {
|
||||
private:
|
||||
GDALWarpOptions *psOptions;
|
||||
|
||||
void WipeOptions();
|
||||
int ValidateOptions();
|
||||
|
||||
CPLErr ComputeSourceWindow( int nDstXOff, int nDstYOff,
|
||||
int nDstXSize, int nDstYSize,
|
||||
int *pnSrcXOff, int *pnSrcYOff,
|
||||
int *pnSrcXSize, int *pnSrcYSize,
|
||||
int *pnSrcXExtraSize, int *pnSrcYExtraSize,
|
||||
double* pdfSrcFillRatio );
|
||||
|
||||
CPLErr CreateKernelMask( GDALWarpKernel *, int iBand,
|
||||
const char *pszType );
|
||||
|
||||
CPLMutex *hIOMutex;
|
||||
CPLMutex *hWarpMutex;
|
||||
|
||||
int nChunkListCount;
|
||||
int nChunkListMax;
|
||||
GDALWarpChunk *pasChunkList;
|
||||
|
||||
int bReportTimings;
|
||||
unsigned long nLastTimeReported;
|
||||
|
||||
void WipeChunkList();
|
||||
CPLErr CollectChunkList( int nDstXOff, int nDstYOff,
|
||||
int nDstXSize, int nDstYSize );
|
||||
void ReportTiming( const char * );
|
||||
|
||||
public:
|
||||
GDALWarpOperation();
|
||||
virtual ~GDALWarpOperation();
|
||||
|
||||
CPLErr Initialize( const GDALWarpOptions *psNewOptions );
|
||||
|
||||
const GDALWarpOptions *GetOptions();
|
||||
|
||||
CPLErr ChunkAndWarpImage( int nDstXOff, int nDstYOff,
|
||||
int nDstXSize, int nDstYSize );
|
||||
CPLErr ChunkAndWarpMulti( int nDstXOff, int nDstYOff,
|
||||
int nDstXSize, int nDstYSize );
|
||||
CPLErr WarpRegion( int nDstXOff, int nDstYOff,
|
||||
int nDstXSize, int nDstYSize,
|
||||
int nSrcXOff=0, int nSrcYOff=0,
|
||||
int nSrcXSize=0, int nSrcYSize=0,
|
||||
double dfProgressBase=0.0, double dfProgressScale=1.0);
|
||||
CPLErr WarpRegion( int nDstXOff, int nDstYOff,
|
||||
int nDstXSize, int nDstYSize,
|
||||
int nSrcXOff, int nSrcYOff,
|
||||
int nSrcXSize, int nSrcYSize,
|
||||
int nSrcXExtraSize, int nSrcYExtraSize,
|
||||
double dfProgressBase, double dfProgressScale);
|
||||
CPLErr WarpRegionToBuffer( int nDstXOff, int nDstYOff,
|
||||
int nDstXSize, int nDstYSize,
|
||||
void *pDataBuf,
|
||||
GDALDataType eBufDataType,
|
||||
int nSrcXOff=0, int nSrcYOff=0,
|
||||
int nSrcXSize=0, int nSrcYSize=0,
|
||||
double dfProgressBase=0.0, double dfProgressScale=1.0);
|
||||
CPLErr WarpRegionToBuffer( int nDstXOff, int nDstYOff,
|
||||
int nDstXSize, int nDstYSize,
|
||||
void *pDataBuf,
|
||||
GDALDataType eBufDataType,
|
||||
int nSrcXOff, int nSrcYOff,
|
||||
int nSrcXSize, int nSrcYSize,
|
||||
int nSrcXExtraSize, int nSrcYExtraSize,
|
||||
double dfProgressBase, double dfProgressScale);
|
||||
};
|
||||
|
||||
#endif /* def __cplusplus */
|
||||
|
||||
CPL_C_START
|
||||
|
||||
typedef void * GDALWarpOperationH;
|
||||
|
||||
GDALWarpOperationH CPL_DLL GDALCreateWarpOperation(const GDALWarpOptions* );
|
||||
void CPL_DLL GDALDestroyWarpOperation( GDALWarpOperationH );
|
||||
CPLErr CPL_DLL GDALChunkAndWarpImage( GDALWarpOperationH, int, int, int, int );
|
||||
CPLErr CPL_DLL GDALChunkAndWarpMulti( GDALWarpOperationH, int, int, int, int );
|
||||
CPLErr CPL_DLL GDALWarpRegion( GDALWarpOperationH,
|
||||
int, int, int, int, int, int, int, int );
|
||||
CPLErr CPL_DLL GDALWarpRegionToBuffer( GDALWarpOperationH, int, int, int, int,
|
||||
void *, GDALDataType,
|
||||
int, int, int, int );
|
||||
|
||||
/************************************************************************/
|
||||
/* Warping kernel functions */
|
||||
/************************************************************************/
|
||||
|
||||
int GWKGetFilterRadius(GDALResampleAlg eResampleAlg);
|
||||
|
||||
typedef double (*FilterFuncType)(double dfX);
|
||||
FilterFuncType GWKGetFilterFunc(GDALResampleAlg eResampleAlg);
|
||||
|
||||
typedef double (*FilterFunc4ValuesType)(double* padfVals);
|
||||
FilterFunc4ValuesType GWKGetFilterFunc4Values(GDALResampleAlg eResampleAlg);
|
||||
|
||||
CPL_C_END
|
||||
|
||||
#endif /* ndef GDAL_ALG_H_INCLUDED */
|
||||
5081
bazaar/plugin/gdal/alg/gdalwarpkernel.cpp
Normal file
5081
bazaar/plugin/gdal/alg/gdalwarpkernel.cpp
Normal file
File diff suppressed because it is too large
Load diff
2575
bazaar/plugin/gdal/alg/gdalwarpkernel_opencl.c
Normal file
2575
bazaar/plugin/gdal/alg/gdalwarpkernel_opencl.c
Normal file
File diff suppressed because it is too large
Load diff
198
bazaar/plugin/gdal/alg/gdalwarpkernel_opencl.h
Normal file
198
bazaar/plugin/gdal/alg/gdalwarpkernel_opencl.h
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/******************************************************************************
|
||||
* $Id: gdalwarpkernel_opencl.h 25068 2012-10-07 14:01:47Z rouault $
|
||||
*
|
||||
* Project: OpenCL Image Reprojector
|
||||
* Purpose: Implementation of the GDALWarpKernel reprojector in OpenCL.
|
||||
* Author: Seth Price, seth@pricepages.org
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2010, Seth Price <seth@pricepages.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(HAVE_OPENCL)
|
||||
|
||||
/* The following relates to the profiling calls to
|
||||
clSetCommandQueueProperty() which are not available by default
|
||||
with some OpenCL implementation (ie. ATI) */
|
||||
|
||||
#if defined(DEBUG_OPENCL) && DEBUG_OPENCL == 1
|
||||
#define CL_USE_DEPRECATED_OPENCL_1_0_APIS
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <OpenCL/OpenCL.h>
|
||||
#else
|
||||
#include <CL/opencl.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
OCL_Bilinear=10,
|
||||
OCL_Cubic=11,
|
||||
OCL_CubicSpline=12,
|
||||
OCL_Lanczos=13
|
||||
} OCLResampAlg;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VENDOR_OTHER,
|
||||
VENDOR_AMD,
|
||||
VENDOR_INTEL
|
||||
} OCLVendor;
|
||||
|
||||
struct oclWarper {
|
||||
cl_command_queue queue;
|
||||
cl_context context;
|
||||
cl_device_id dev;
|
||||
cl_kernel kern1;
|
||||
cl_kernel kern4;
|
||||
|
||||
int srcWidth;
|
||||
int srcHeight;
|
||||
int dstWidth;
|
||||
int dstHeight;
|
||||
|
||||
int useUnifiedSrcDensity;
|
||||
int useUnifiedSrcValid;
|
||||
int useDstDensity;
|
||||
int useDstValid;
|
||||
|
||||
int numBands;
|
||||
int numImages;
|
||||
OCLResampAlg resampAlg;
|
||||
|
||||
cl_channel_type imageFormat;
|
||||
cl_mem *realWorkCL;
|
||||
union {
|
||||
void **v;
|
||||
char **c;
|
||||
unsigned char **uc;
|
||||
short **s;
|
||||
unsigned short **us;
|
||||
float **f;
|
||||
} realWork;
|
||||
|
||||
cl_mem *imagWorkCL;
|
||||
union {
|
||||
void **v;
|
||||
char **c;
|
||||
unsigned char **uc;
|
||||
short **s;
|
||||
unsigned short **us;
|
||||
float **f;
|
||||
} imagWork;
|
||||
|
||||
cl_mem *dstRealWorkCL;
|
||||
union {
|
||||
void **v;
|
||||
char **c;
|
||||
unsigned char **uc;
|
||||
short **s;
|
||||
unsigned short **us;
|
||||
float **f;
|
||||
} dstRealWork;
|
||||
|
||||
cl_mem *dstImagWorkCL;
|
||||
union {
|
||||
void **v;
|
||||
char **c;
|
||||
unsigned char **uc;
|
||||
short **s;
|
||||
unsigned short **us;
|
||||
float **f;
|
||||
} dstImagWork;
|
||||
|
||||
unsigned int imgChSize1;
|
||||
cl_channel_order imgChOrder1;
|
||||
unsigned int imgChSize4;
|
||||
cl_channel_order imgChOrder4;
|
||||
char useVec;
|
||||
|
||||
cl_mem useBandSrcValidCL;
|
||||
char *useBandSrcValid;
|
||||
|
||||
cl_mem nBandSrcValidCL;
|
||||
float *nBandSrcValid;
|
||||
|
||||
cl_mem xyWorkCL;
|
||||
float *xyWork;
|
||||
|
||||
int xyWidth;
|
||||
int xyHeight;
|
||||
int coordMult;
|
||||
|
||||
unsigned int xyChSize;
|
||||
cl_channel_order xyChOrder;
|
||||
|
||||
cl_mem fDstNoDataRealCL;
|
||||
float *fDstNoDataReal;
|
||||
|
||||
OCLVendor eCLVendor;
|
||||
};
|
||||
|
||||
struct oclWarper* GDALWarpKernelOpenCL_createEnv(int srcWidth, int srcHeight,
|
||||
int dstWidth, int dstHeight,
|
||||
cl_channel_type imageFormat,
|
||||
int numBands, int coordMult,
|
||||
int useImag, int useBandSrcValid,
|
||||
float *fDstDensity,
|
||||
double *dfDstNoDataReal,
|
||||
OCLResampAlg resampAlg, cl_int *envErr);
|
||||
|
||||
cl_int GDALWarpKernelOpenCL_setSrcValid(struct oclWarper *warper,
|
||||
int *bandSrcValid, int bandNum);
|
||||
|
||||
cl_int GDALWarpKernelOpenCL_setSrcImg(struct oclWarper *warper, void *imgData,
|
||||
int bandNum);
|
||||
|
||||
cl_int GDALWarpKernelOpenCL_setDstImg(struct oclWarper *warper, void *imgData,
|
||||
int bandNum);
|
||||
|
||||
cl_int GDALWarpKernelOpenCL_setCoordRow(struct oclWarper *warper,
|
||||
double *rowSrcX, double *rowSrcY,
|
||||
double srcXOff, double srcYOff,
|
||||
int *success, int rowNum);
|
||||
|
||||
cl_int GDALWarpKernelOpenCL_runResamp(struct oclWarper *warper,
|
||||
float *unifiedSrcDensity,
|
||||
unsigned int *unifiedSrcValid,
|
||||
float *dstDensity,
|
||||
unsigned int *dstValid,
|
||||
double dfXScale, double dfYScale,
|
||||
double dfXFilter, double dfYFilter,
|
||||
int nXRadius, int nYRadius,
|
||||
int nFiltInitX, int nFiltInitY);
|
||||
|
||||
cl_int GDALWarpKernelOpenCL_getRow(struct oclWarper *warper,
|
||||
void **rowReal, void **rowImag,
|
||||
int rowNum, int bandNum);
|
||||
|
||||
cl_int GDALWarpKernelOpenCL_deleteEnv(struct oclWarper *warper);
|
||||
|
||||
#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* defined(HAVE_OPENCL) */
|
||||
|
||||
2391
bazaar/plugin/gdal/alg/gdalwarpoperation.cpp
Normal file
2391
bazaar/plugin/gdal/alg/gdalwarpoperation.cpp
Normal file
File diff suppressed because it is too large
Load diff
94
bazaar/plugin/gdal/alg/gvgcpfit.h
Normal file
94
bazaar/plugin/gdal/alg/gvgcpfit.h
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
#ifndef _GVGCPFIT_H_INCLUDED
|
||||
#define _GVGCPFIT_H_INCLUDED
|
||||
|
||||
#include "cpl_port.h"
|
||||
#include "cpl_conv.h"
|
||||
#include "cpl_error.h"
|
||||
|
||||
#define EXTERNAL
|
||||
#define LOCAL static
|
||||
|
||||
#define SUCCESS 0
|
||||
#define ABORT -1
|
||||
|
||||
|
||||
/*------------------------ Start of file CURVEFIT.H -----------------------*/
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* *
|
||||
* CURVEFIT.H *
|
||||
* ========= *
|
||||
* *
|
||||
* This file contains the function prototype for CURVEFIT.C. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CURVEFIT_H
|
||||
#define CURVEFIT_H
|
||||
|
||||
/*- Function prototypes in CURVEFIT.C. -*/
|
||||
|
||||
EXTERNAL int svdfit(float x[], float y[], int ndata,
|
||||
double a[], int ma, double **u, double **v, double w[],
|
||||
double *chisq, void (*funcs)(double, double *, int));
|
||||
|
||||
EXTERNAL void svbksb(double **u, double w[], double **v, int m,int n,
|
||||
double b[], double x[]);
|
||||
|
||||
EXTERNAL void svdvar(double **v, int ma, double w[], double **cvm);
|
||||
|
||||
EXTERNAL int svdcmp(double **a, int m, int n, double *w, double **v);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*-------------------------- End of file CURVEFIT.H -----------------------*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*----------------------------- FILE polyfit.h ----------------------------*/
|
||||
#ifndef __POLYFIT_H
|
||||
#define __POLYFIT_H
|
||||
|
||||
EXTERNAL int OneDPolyFit( double *rms_err, double *coeffs_array,
|
||||
int fit_order, int no_samples, double *f_array, double *x_array );
|
||||
|
||||
EXTERNAL double OneDPolyEval( double *coeff, int order, double x );
|
||||
|
||||
EXTERNAL int TwoDPolyFit( double *rms_err, double *coeffs_array,
|
||||
int fit_order, int no_samples, double *f_array, double *x_array,
|
||||
double *y_array );
|
||||
|
||||
EXTERNAL double TwoDPolyEval( double *coeff, int order, double x, double y );
|
||||
|
||||
EXTERNAL int TwoDPolyGradFit( double *rms_err, double *coeffs_array,
|
||||
int fit_order, int no_samples, double *gradxy_array,
|
||||
double *x_array, double *y_array );
|
||||
|
||||
EXTERNAL void TwoDPolyGradEval(double *fgradx, double *fgrady,
|
||||
double *coeff, int order, double x, double y);
|
||||
|
||||
EXTERNAL void GetPolyInX (double *xcoeffs, double *xycoeffs, int order,
|
||||
double y);
|
||||
|
||||
EXTERNAL void GetPolyInY(double *ycoeffs, double *xycoeffs, int order,
|
||||
double x);
|
||||
|
||||
EXTERNAL int ThreeDPolyFit( double *rms_err, double *coeffs_array,
|
||||
int fit_order, int no_samples, double *f_array, double *x_array,
|
||||
double *y_array, double *z_array );
|
||||
|
||||
EXTERNAL double ThreeDPolyEval( double *coeff, int order, double x, double y, double z );
|
||||
|
||||
|
||||
|
||||
#endif /* __POLYFIT_H */
|
||||
|
||||
|
||||
/*---------------------- End of FILE polyfit.h ----------------------------*/
|
||||
|
||||
#endif /* ndef _GVGCPFIT_INCLUDED */
|
||||
606
bazaar/plugin/gdal/alg/llrasterize.cpp
Normal file
606
bazaar/plugin/gdal/alg/llrasterize.cpp
Normal file
|
|
@ -0,0 +1,606 @@
|
|||
/******************************************************************************
|
||||
* $Id: llrasterize.cpp 29117 2015-05-02 20:50:05Z rouault $
|
||||
*
|
||||
* Project: GDAL
|
||||
* Purpose: Vector polygon rasterization code.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2000, Frank Warmerdam <warmerdam@pobox.com>
|
||||
* Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_alg.h"
|
||||
#include "gdal_alg_priv.h"
|
||||
|
||||
static int llCompareInt(const void *a, const void *b)
|
||||
{
|
||||
return (*(const int *)a) - (*(const int *)b);
|
||||
}
|
||||
|
||||
static void llSwapDouble(double *a, double *b)
|
||||
{
|
||||
double temp = *a;
|
||||
*a = *b;
|
||||
*b = temp;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* dllImageFilledPolygon() */
|
||||
/* */
|
||||
/* Perform scanline conversion of the passed multi-ring */
|
||||
/* polygon. Note the polygon does not need to be explicitly */
|
||||
/* closed. The scanline function will be called with */
|
||||
/* horizontal scanline chunks which may not be entirely */
|
||||
/* contained within the valid raster area (in the X */
|
||||
/* direction). */
|
||||
/* */
|
||||
/* NEW: Nodes' coordinate are kept as double in order */
|
||||
/* to compute accurately the intersections with the lines */
|
||||
/* */
|
||||
/* Two methods for determining the border pixels: */
|
||||
/* */
|
||||
/* 1) method = 0 */
|
||||
/* Inherits algorithm from version above but with several bugs */
|
||||
/* fixed except for the cone facing down. */
|
||||
/* A pixel on which a line intersects a segment of a */
|
||||
/* polygon will always be considered as inside the shape. */
|
||||
/* Note that we only compute intersections with lines that */
|
||||
/* passes through the middle of a pixel (line coord = 0.5, */
|
||||
/* 1.5, 2.5, etc.) */
|
||||
/* */
|
||||
/* 2) method = 1: */
|
||||
/* A pixel is considered inside a polygon if its center */
|
||||
/* falls inside the polygon. This is somehow more robust unless */
|
||||
/* the nodes are placed in the center of the pixels in which */
|
||||
/* case, due to numerical inaccuracies, it's hard to predict */
|
||||
/* if the pixel will be considered inside or outside the shape. */
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
* NOTE: This code was originally adapted from the gdImageFilledPolygon()
|
||||
* function in libgd.
|
||||
*
|
||||
* http://www.boutell.com/gd/
|
||||
*
|
||||
* It was later adapted for direct inclusion in GDAL and relicensed under
|
||||
* the GDAL MIT/X license (pulled from the OpenEV distribution).
|
||||
*/
|
||||
|
||||
void GDALdllImageFilledPolygon(int nRasterXSize, int nRasterYSize,
|
||||
int nPartCount, int *panPartSize,
|
||||
double *padfX, double *padfY,
|
||||
double *dfVariant,
|
||||
llScanlineFunc pfnScanlineFunc, void *pCBData )
|
||||
{
|
||||
/*************************************************************************
|
||||
2nd Method (method=1):
|
||||
=====================
|
||||
No known bug
|
||||
*************************************************************************/
|
||||
|
||||
int i;
|
||||
int y;
|
||||
int miny, maxy,minx,maxx;
|
||||
double dminy, dmaxy;
|
||||
double dx1, dy1;
|
||||
double dx2, dy2;
|
||||
double dy;
|
||||
double intersect;
|
||||
|
||||
int ind1, ind2;
|
||||
int ints, n, part;
|
||||
int *polyInts;
|
||||
|
||||
int horizontal_x1, horizontal_x2;
|
||||
|
||||
if (!nPartCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
for( part = 0; part < nPartCount; part++ )
|
||||
n += panPartSize[part];
|
||||
|
||||
polyInts = (int *) malloc(sizeof(int) * n);
|
||||
|
||||
dminy = padfY[0];
|
||||
dmaxy = padfY[0];
|
||||
for (i=1; (i < n); i++) {
|
||||
|
||||
if (padfY[i] < dminy) {
|
||||
dminy = padfY[i];
|
||||
}
|
||||
if (padfY[i] > dmaxy) {
|
||||
dmaxy = padfY[i];
|
||||
}
|
||||
}
|
||||
miny = (int) dminy;
|
||||
maxy = (int) dmaxy;
|
||||
|
||||
|
||||
if( miny < 0 )
|
||||
miny = 0;
|
||||
if( maxy >= nRasterYSize )
|
||||
maxy = nRasterYSize-1;
|
||||
|
||||
|
||||
minx = 0;
|
||||
maxx = nRasterXSize - 1;
|
||||
|
||||
/* Fix in 1.3: count a vertex only once */
|
||||
for (y=miny; y <= maxy; y++) {
|
||||
int partoffset = 0;
|
||||
|
||||
dy = y +0.5; /* center height of line*/
|
||||
|
||||
|
||||
part = 0;
|
||||
ints = 0;
|
||||
|
||||
/*Initialize polyInts, otherwise it can sometimes causes a seg fault */
|
||||
memset(polyInts, -1, sizeof(int) * n);
|
||||
|
||||
for (i=0; (i < n); i++) {
|
||||
|
||||
|
||||
if( i == partoffset + panPartSize[part] ) {
|
||||
partoffset += panPartSize[part];
|
||||
part++;
|
||||
}
|
||||
|
||||
if( i == partoffset ) {
|
||||
ind1 = partoffset + panPartSize[part] - 1;
|
||||
ind2 = partoffset;
|
||||
} else {
|
||||
ind1 = i-1;
|
||||
ind2 = i;
|
||||
}
|
||||
|
||||
|
||||
dy1 = padfY[ind1];
|
||||
dy2 = padfY[ind2];
|
||||
|
||||
|
||||
if( (dy1 < dy && dy2 < dy) || (dy1 > dy && dy2 > dy) )
|
||||
continue;
|
||||
|
||||
if (dy1 < dy2) {
|
||||
dx1 = padfX[ind1];
|
||||
dx2 = padfX[ind2];
|
||||
} else if (dy1 > dy2) {
|
||||
dy2 = padfY[ind1];
|
||||
dy1 = padfY[ind2];
|
||||
dx2 = padfX[ind1];
|
||||
dx1 = padfX[ind2];
|
||||
} else /* if (fabs(dy1-dy2)< 1.e-6) */
|
||||
{
|
||||
|
||||
/*AE: DO NOT skip bottom horizontal segments
|
||||
-Fill them separately-
|
||||
They are not taken into account twice.*/
|
||||
if (padfX[ind1] > padfX[ind2])
|
||||
{
|
||||
horizontal_x1 = (int) floor(padfX[ind2]+0.5);
|
||||
horizontal_x2 = (int) floor(padfX[ind1]+0.5);
|
||||
|
||||
if ( (horizontal_x1 > maxx) || (horizontal_x2 <= minx) )
|
||||
continue;
|
||||
|
||||
/*fill the horizontal segment (separately from the rest)*/
|
||||
pfnScanlineFunc( pCBData, y, horizontal_x1, horizontal_x2 - 1, (dfVariant == NULL)?0:dfVariant[0] );
|
||||
continue;
|
||||
}
|
||||
else /*skip top horizontal segments (they are already filled in the regular loop)*/
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if(( dy < dy2 ) && (dy >= dy1))
|
||||
{
|
||||
|
||||
intersect = (dy-dy1) * (dx2-dx1) / (dy2-dy1) + dx1;
|
||||
|
||||
polyInts[ints++] = (int) floor(intersect+0.5);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* It would be more efficient to do this inline, to avoid
|
||||
* a function call for each comparison.
|
||||
* NOTE - mloskot: make llCompareInt a functor and use std
|
||||
* algorithm and it will be optimized and expanded
|
||||
* automatically in compile-time, with modularity preserved.
|
||||
*/
|
||||
qsort(polyInts, ints, sizeof(int), llCompareInt);
|
||||
|
||||
|
||||
for (i=0; (i < (ints)); i+=2)
|
||||
{
|
||||
if( polyInts[i] <= maxx && polyInts[i+1] > minx )
|
||||
{
|
||||
pfnScanlineFunc( pCBData, y, polyInts[i], polyInts[i+1] - 1, (dfVariant == NULL)?0:dfVariant[0] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free( polyInts );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALdllImagePoint() */
|
||||
/************************************************************************/
|
||||
|
||||
void GDALdllImagePoint( int nRasterXSize, int nRasterYSize,
|
||||
int nPartCount,
|
||||
CPL_UNUSED int *panPartSize,
|
||||
double *padfX, double *padfY, double *padfVariant,
|
||||
llPointFunc pfnPointFunc, void *pCBData )
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < nPartCount; i++ )
|
||||
{
|
||||
int nX = (int)floor( padfX[i] );
|
||||
int nY = (int)floor( padfY[i] );
|
||||
double dfVariant = 0;
|
||||
if( padfVariant != NULL )
|
||||
dfVariant = padfVariant[i];
|
||||
|
||||
if ( 0 <= nX && nX < nRasterXSize && 0 <= nY && nY < nRasterYSize )
|
||||
pfnPointFunc( pCBData, nY, nX, dfVariant );
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALdllImageLine() */
|
||||
/************************************************************************/
|
||||
|
||||
void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
|
||||
int nPartCount, int *panPartSize,
|
||||
double *padfX, double *padfY, double *padfVariant,
|
||||
llPointFunc pfnPointFunc, void *pCBData )
|
||||
{
|
||||
int i, n;
|
||||
|
||||
if ( !nPartCount )
|
||||
return;
|
||||
|
||||
for ( i = 0, n = 0; i < nPartCount; n += panPartSize[i++] )
|
||||
{
|
||||
int j;
|
||||
|
||||
for ( j = 1; j < panPartSize[i]; j++ )
|
||||
{
|
||||
int iX = (int)floor( padfX[n + j - 1] );
|
||||
int iY = (int)floor( padfY[n + j - 1] );
|
||||
|
||||
const int iX1 = (int)floor( padfX[n + j] );
|
||||
const int iY1 = (int)floor( padfY[n + j] );
|
||||
|
||||
double dfVariant = 0, dfVariant1 = 0;
|
||||
if( padfVariant != NULL &&
|
||||
((GDALRasterizeInfo *)pCBData)->eBurnValueSource !=
|
||||
GBV_UserBurnValue )
|
||||
{
|
||||
dfVariant = padfVariant[n + j - 1];
|
||||
dfVariant1 = padfVariant[n + j];
|
||||
}
|
||||
|
||||
int nDeltaX = ABS( iX1 - iX );
|
||||
int nDeltaY = ABS( iY1 - iY );
|
||||
|
||||
// Step direction depends on line direction.
|
||||
const int nXStep = ( iX > iX1 ) ? -1 : 1;
|
||||
const int nYStep = ( iY > iY1 ) ? -1 : 1;
|
||||
|
||||
// Determine the line slope.
|
||||
if ( nDeltaX >= nDeltaY )
|
||||
{
|
||||
const int nXError = nDeltaY << 1;
|
||||
const int nYError = nXError - (nDeltaX << 1);
|
||||
int nError = nXError - nDeltaX;
|
||||
/* == 0 makes clang -fcatch-undefined-behavior -ftrapv happy, but if */
|
||||
/* it is == 0, dfDeltaVariant is not really used, so any value is OK */
|
||||
double dfDeltaVariant = (nDeltaX == 0) ? 0 : (dfVariant1 - dfVariant) /
|
||||
(double)nDeltaX;
|
||||
|
||||
while ( nDeltaX-- >= 0 )
|
||||
{
|
||||
if ( 0 <= iX && iX < nRasterXSize
|
||||
&& 0 <= iY && iY < nRasterYSize )
|
||||
pfnPointFunc( pCBData, iY, iX, dfVariant );
|
||||
|
||||
dfVariant += dfDeltaVariant;
|
||||
iX += nXStep;
|
||||
if ( nError > 0 )
|
||||
{
|
||||
iY += nYStep;
|
||||
nError += nYError;
|
||||
}
|
||||
else
|
||||
nError += nXError;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const int nXError = nDeltaX << 1;
|
||||
const int nYError = nXError - (nDeltaY << 1);
|
||||
int nError = nXError - nDeltaY;
|
||||
/* == 0 makes clang -fcatch-undefined-behavior -ftrapv happy, but if */
|
||||
/* it is == 0, dfDeltaVariant is not really used, so any value is OK */
|
||||
double dfDeltaVariant = (nDeltaY == 0) ? 0 : (dfVariant1 - dfVariant) /
|
||||
(double)nDeltaY;
|
||||
|
||||
while ( nDeltaY-- >= 0 )
|
||||
{
|
||||
if ( 0 <= iX && iX < nRasterXSize
|
||||
&& 0 <= iY && iY < nRasterYSize )
|
||||
pfnPointFunc( pCBData, iY, iX, dfVariant );
|
||||
|
||||
dfVariant += dfDeltaVariant;
|
||||
iY += nYStep;
|
||||
if ( nError > 0 )
|
||||
{
|
||||
iX += nXStep;
|
||||
nError += nYError;
|
||||
}
|
||||
else
|
||||
nError += nXError;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALdllImageLineAllTouched() */
|
||||
/* */
|
||||
/* This alternate line drawing algorithm attempts to ensure */
|
||||
/* that every pixel touched at all by the line will get set. */
|
||||
/* @param padfVariant should contain the values that are to be */
|
||||
/* added to the burn value. The values along the line between the */
|
||||
/* points will be linearly interpolated. These values are used */
|
||||
/* only if pCBData->eBurnValueSource is set to something other */
|
||||
/* than GBV_UserBurnValue. If NULL is passed, a monotonous line */
|
||||
/* will be drawn with the burn value. */
|
||||
/************************************************************************/
|
||||
|
||||
void
|
||||
GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
|
||||
int nPartCount, int *panPartSize,
|
||||
double *padfX, double *padfY, double *padfVariant,
|
||||
llPointFunc pfnPointFunc, void *pCBData )
|
||||
|
||||
{
|
||||
int i, n;
|
||||
|
||||
if ( !nPartCount )
|
||||
return;
|
||||
|
||||
for ( i = 0, n = 0; i < nPartCount; n += panPartSize[i++] )
|
||||
{
|
||||
int j;
|
||||
|
||||
for ( j = 1; j < panPartSize[i]; j++ )
|
||||
{
|
||||
double dfX = padfX[n + j - 1];
|
||||
double dfY = padfY[n + j - 1];
|
||||
|
||||
double dfXEnd = padfX[n + j];
|
||||
double dfYEnd = padfY[n + j];
|
||||
|
||||
double dfVariant = 0, dfVariantEnd = 0;
|
||||
if( padfVariant != NULL &&
|
||||
((GDALRasterizeInfo *)pCBData)->eBurnValueSource !=
|
||||
GBV_UserBurnValue )
|
||||
{
|
||||
dfVariant = padfVariant[n + j - 1];
|
||||
dfVariantEnd = padfVariant[n + j];
|
||||
}
|
||||
|
||||
// Skip segments that are off the target region.
|
||||
if( (dfY < 0 && dfYEnd < 0)
|
||||
|| (dfY > nRasterYSize && dfYEnd > nRasterYSize)
|
||||
|| (dfX < 0 && dfXEnd < 0)
|
||||
|| (dfX > nRasterXSize && dfXEnd > nRasterXSize) )
|
||||
continue;
|
||||
|
||||
// Swap if needed so we can proceed from left2right (X increasing)
|
||||
if( dfX > dfXEnd )
|
||||
{
|
||||
llSwapDouble( &dfX, &dfXEnd );
|
||||
llSwapDouble( &dfY, &dfYEnd );
|
||||
llSwapDouble( &dfVariant, &dfVariantEnd );
|
||||
}
|
||||
|
||||
// Special case for vertical lines.
|
||||
if( floor(dfX) == floor(dfXEnd) )
|
||||
{
|
||||
if( dfYEnd < dfY )
|
||||
{
|
||||
llSwapDouble( &dfY, &dfYEnd );
|
||||
llSwapDouble( &dfVariant, &dfVariantEnd );
|
||||
}
|
||||
|
||||
int iX = (int) floor(dfX);
|
||||
int iY = (int) floor(dfY);
|
||||
int iYEnd = (int) floor(dfYEnd);
|
||||
|
||||
if( iX >= nRasterXSize )
|
||||
continue;
|
||||
|
||||
double dfDeltaVariant = 0;
|
||||
if(( dfYEnd - dfY ) > 0)
|
||||
dfDeltaVariant = ( dfVariantEnd - dfVariant )
|
||||
/ ( dfYEnd - dfY );//per unit change in iY
|
||||
|
||||
// Clip to the borders of the target region
|
||||
if( iY < 0 )
|
||||
iY = 0;
|
||||
if( iYEnd >= nRasterYSize )
|
||||
iYEnd = nRasterYSize - 1;
|
||||
dfVariant += dfDeltaVariant * ( (double)iY - dfY );
|
||||
|
||||
if( padfVariant == NULL )
|
||||
for( ; iY <= iYEnd; iY++ )
|
||||
pfnPointFunc( pCBData, iY, iX, 0.0 );
|
||||
else
|
||||
for( ; iY <= iYEnd; iY++, dfVariant += dfDeltaVariant )
|
||||
pfnPointFunc( pCBData, iY, iX, dfVariant );
|
||||
|
||||
continue; // next segment
|
||||
}
|
||||
|
||||
double dfDeltaVariant = ( dfVariantEnd - dfVariant )
|
||||
/ ( dfXEnd - dfX );//per unit change in iX
|
||||
|
||||
// special case for horizontal lines
|
||||
if( floor(dfY) == floor(dfYEnd) )
|
||||
{
|
||||
if( dfXEnd < dfX )
|
||||
{
|
||||
llSwapDouble( &dfX, &dfXEnd );
|
||||
llSwapDouble( &dfVariant, &dfVariantEnd );
|
||||
}
|
||||
|
||||
int iX = (int) floor(dfX);
|
||||
int iY = (int) floor(dfY);
|
||||
int iXEnd = (int) floor(dfXEnd);
|
||||
|
||||
if( iY >= nRasterYSize )
|
||||
continue;
|
||||
|
||||
// Clip to the borders of the target region
|
||||
if( iX < 0 )
|
||||
iX = 0;
|
||||
if( iXEnd >= nRasterXSize )
|
||||
iXEnd = nRasterXSize - 1;
|
||||
dfVariant += dfDeltaVariant * ( (double)iX - dfX );
|
||||
|
||||
if( padfVariant == NULL )
|
||||
for( ; iX <= iXEnd; iX++ )
|
||||
pfnPointFunc( pCBData, iY, iX, 0.0 );
|
||||
else
|
||||
for( ; iX <= iXEnd; iX++, dfVariant += dfDeltaVariant )
|
||||
pfnPointFunc( pCBData, iY, iX, dfVariant );
|
||||
|
||||
continue; // next segment
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* General case - left to right sloped. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
double dfSlope = (dfYEnd - dfY) / (dfXEnd - dfX);
|
||||
|
||||
// clip segment in X
|
||||
if( dfXEnd > nRasterXSize )
|
||||
{
|
||||
dfYEnd -= ( dfXEnd - (double)nRasterXSize ) * dfSlope;
|
||||
dfXEnd = nRasterXSize;
|
||||
}
|
||||
if( dfX < 0 )
|
||||
{
|
||||
dfY += (0 - dfX) * dfSlope;
|
||||
dfVariant += dfDeltaVariant * (0.0 - dfX);
|
||||
dfX = 0.0;
|
||||
}
|
||||
|
||||
// clip segment in Y
|
||||
double dfDiffX;
|
||||
if( dfYEnd > dfY )
|
||||
{
|
||||
if( dfY < 0 )
|
||||
{
|
||||
dfX += (dfDiffX = (0 - dfY) / dfSlope);
|
||||
dfVariant += dfDeltaVariant * dfDiffX;
|
||||
dfY = 0.0;
|
||||
}
|
||||
if( dfYEnd >= nRasterYSize )
|
||||
{
|
||||
dfXEnd += ( dfYEnd - (double)nRasterYSize ) / dfSlope;
|
||||
dfYEnd = nRasterXSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dfY >= nRasterYSize )
|
||||
{
|
||||
dfX += (dfDiffX = ((double)nRasterYSize - dfY) / dfSlope);
|
||||
dfVariant += dfDeltaVariant * dfDiffX;
|
||||
dfY = nRasterYSize;
|
||||
}
|
||||
if( dfYEnd < 0 )
|
||||
{
|
||||
dfXEnd -= ( dfYEnd - 0 ) / dfSlope;
|
||||
dfYEnd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// step from pixel to pixel.
|
||||
while( dfX >= 0 && dfX < dfXEnd )
|
||||
{
|
||||
int iX = (int) floor(dfX);
|
||||
int iY = (int) floor(dfY);
|
||||
|
||||
// burn in the current point.
|
||||
// We should be able to drop the Y check because we cliped in Y,
|
||||
// but there may be some error with all the small steps.
|
||||
if( iY >= 0 && iY < nRasterYSize )
|
||||
pfnPointFunc( pCBData, iY, iX, dfVariant );
|
||||
|
||||
double dfStepX = floor(dfX+1.0) - dfX;
|
||||
double dfStepY = dfStepX * dfSlope;
|
||||
|
||||
// step to right pixel without changing scanline?
|
||||
if( (int) floor(dfY + dfStepY) == iY )
|
||||
{
|
||||
dfX += dfStepX;
|
||||
dfY += dfStepY;
|
||||
dfVariant += dfDeltaVariant * dfStepX;
|
||||
}
|
||||
else if( dfSlope < 0 )
|
||||
{
|
||||
dfStepY = iY - dfY;
|
||||
if( dfStepY > -0.000000001 )
|
||||
dfStepY = -0.000000001;
|
||||
|
||||
dfStepX = dfStepY / dfSlope;
|
||||
dfX += dfStepX;
|
||||
dfY += dfStepY;
|
||||
dfVariant += dfDeltaVariant * dfStepX;
|
||||
}
|
||||
else
|
||||
{
|
||||
dfStepY = (iY + 1) - dfY;
|
||||
if( dfStepY < 0.000000001 )
|
||||
dfStepY = 0.000000001;
|
||||
|
||||
dfStepX = dfStepY / dfSlope;
|
||||
dfX += dfStepX;
|
||||
dfY += dfStepY;
|
||||
dfVariant += dfDeltaVariant * dfStepX;
|
||||
}
|
||||
} // next step along sement.
|
||||
|
||||
} // next segment
|
||||
} // next part
|
||||
}
|
||||
31
bazaar/plugin/gdal/alg/makefile.vc
Normal file
31
bazaar/plugin/gdal/alg/makefile.vc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
#
|
||||
# Algorithms
|
||||
#
|
||||
|
||||
GDAL_ROOT = ..
|
||||
|
||||
EXTRAFLAGS = -I../ogr/ogrsf_frmts $(GEOS_CFLAGS)
|
||||
|
||||
!INCLUDE ..\nmake.opt
|
||||
|
||||
!IFDEF INCLUDE_OGR_FRMTS
|
||||
EXTRAFLAGS = $(EXTRAFLAGS) -DOGR_ENABLED
|
||||
!ENDIF
|
||||
|
||||
OBJ = gdaldither.obj gdalmediancut.obj gdal_crs.obj gdaltransformer.obj \
|
||||
gdalsimplewarp.obj gdalwarper.obj gdalwarpkernel.obj \
|
||||
thinplatespline.obj gdal_tps.obj gdalrasterize.obj llrasterize.obj \
|
||||
gdalwarpoperation.obj gdalchecksum.obj gdal_rpc.obj gdalgeoloc.obj \
|
||||
gdalgrid.obj gdalgridsse.obj gdalcutline.obj gdalproximity.obj rasterfill.obj \
|
||||
gdalsievefilter.obj gdalrasterpolygonenumerator.obj polygonize.obj \
|
||||
gdalrasterfpolygonenumerator.obj fpolygonize.obj contour.obj \
|
||||
gdal_octave.obj gdal_simplesurf.obj gdalmatching.obj \
|
||||
gdaltransformgeolocs.obj
|
||||
|
||||
|
||||
default: $(OBJ)
|
||||
|
||||
clean:
|
||||
-del *.obj
|
||||
|
||||
761
bazaar/plugin/gdal/alg/polygonize.cpp
Normal file
761
bazaar/plugin/gdal/alg/polygonize.cpp
Normal file
|
|
@ -0,0 +1,761 @@
|
|||
/******************************************************************************
|
||||
* $Id: polygonize.cpp 28826 2015-03-30 17:51:14Z rouault $
|
||||
* Project: GDAL
|
||||
* Purpose: Raster to Polygon Converter
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2008, Frank Warmerdam
|
||||
* Copyright (c) 2009-2011, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_alg_priv.h"
|
||||
#include "cpl_conv.h"
|
||||
#include "cpl_string.h"
|
||||
#include <vector>
|
||||
|
||||
CPL_CVSID("$Id: polygonize.cpp 28826 2015-03-30 17:51:14Z rouault $");
|
||||
|
||||
#ifdef OGR_ENABLED
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* RPolygon */
|
||||
/* */
|
||||
/* This is a helper class to hold polygons while they are being */
|
||||
/* formed in memory, and to provide services to coalesce a much */
|
||||
/* of edge sections into complete rings. */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
class RPolygon {
|
||||
public:
|
||||
RPolygon( int nValue ) { nPolyValue = nValue; nLastLineUpdated = -1; }
|
||||
|
||||
int nPolyValue;
|
||||
int nLastLineUpdated;
|
||||
|
||||
std::vector< std::vector<int> > aanXY;
|
||||
|
||||
void AddSegment( int x1, int y1, int x2, int y2 );
|
||||
void Dump();
|
||||
void Coalesce();
|
||||
void Merge( int iBaseString, int iSrcString, int iDirection );
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* Dump() */
|
||||
/************************************************************************/
|
||||
void RPolygon::Dump()
|
||||
{
|
||||
size_t iString;
|
||||
|
||||
printf( "RPolygon: Value=%d, LastLineUpdated=%d\n",
|
||||
nPolyValue, nLastLineUpdated );
|
||||
|
||||
for( iString = 0; iString < aanXY.size(); iString++ )
|
||||
{
|
||||
std::vector<int> &anString = aanXY[iString];
|
||||
size_t iVert;
|
||||
|
||||
printf( " String %d:\n", (int) iString );
|
||||
for( iVert = 0; iVert < anString.size(); iVert += 2 )
|
||||
{
|
||||
printf( " (%d,%d)\n", anString[iVert], anString[iVert+1] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Coalesce() */
|
||||
/************************************************************************/
|
||||
|
||||
void RPolygon::Coalesce()
|
||||
|
||||
{
|
||||
size_t iBaseString;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Iterate over loops starting from the first, trying to merge */
|
||||
/* other segments into them. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( iBaseString = 0; iBaseString < aanXY.size(); iBaseString++ )
|
||||
{
|
||||
std::vector<int> &anBase = aanXY[iBaseString];
|
||||
int bMergeHappened = TRUE;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Keep trying to merge the following strings into our target */
|
||||
/* "base" string till we have tried them all once without any */
|
||||
/* mergers. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
while( bMergeHappened )
|
||||
{
|
||||
size_t iString;
|
||||
|
||||
bMergeHappened = FALSE;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Loop over the following strings, trying to find one we can */
|
||||
/* merge onto the end of our base string. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( iString = iBaseString+1;
|
||||
iString < aanXY.size();
|
||||
iString++ )
|
||||
{
|
||||
std::vector<int> &anString = aanXY[iString];
|
||||
|
||||
if( anBase[anBase.size()-2] == anString[0]
|
||||
&& anBase[anBase.size()-1] == anString[1] )
|
||||
{
|
||||
Merge( iBaseString, iString, 1 );
|
||||
bMergeHappened = TRUE;
|
||||
}
|
||||
else if( anBase[anBase.size()-2] == anString[anString.size()-2]
|
||||
&& anBase[anBase.size()-1] == anString[anString.size()-1] )
|
||||
{
|
||||
Merge( iBaseString, iString, -1 );
|
||||
bMergeHappened = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point our loop *should* be closed! */
|
||||
|
||||
CPLAssert( anBase[0] == anBase[anBase.size()-2]
|
||||
&& anBase[1] == anBase[anBase.size()-1] );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Merge() */
|
||||
/************************************************************************/
|
||||
|
||||
void RPolygon::Merge( int iBaseString, int iSrcString, int iDirection )
|
||||
|
||||
{
|
||||
std::vector<int> &anBase = aanXY[iBaseString];
|
||||
std::vector<int> &anString = aanXY[iSrcString];
|
||||
int iStart, iEnd, i;
|
||||
|
||||
if( iDirection == 1 )
|
||||
{
|
||||
iStart = 1;
|
||||
iEnd = anString.size() / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
iStart = anString.size() / 2 - 2;
|
||||
iEnd = -1;
|
||||
}
|
||||
|
||||
for( i = iStart; i != iEnd; i += iDirection )
|
||||
{
|
||||
anBase.push_back( anString[i*2+0] );
|
||||
anBase.push_back( anString[i*2+1] );
|
||||
}
|
||||
|
||||
if( iSrcString < ((int) aanXY.size())-1 )
|
||||
aanXY[iSrcString] = aanXY[aanXY.size()-1];
|
||||
|
||||
size_t nSize = aanXY.size();
|
||||
aanXY.resize(nSize-1);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* AddSegment() */
|
||||
/************************************************************************/
|
||||
|
||||
void RPolygon::AddSegment( int x1, int y1, int x2, int y2 )
|
||||
|
||||
{
|
||||
nLastLineUpdated = MAX(y1, y2);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Is there an existing string ending with this? */
|
||||
/* -------------------------------------------------------------------- */
|
||||
size_t iString;
|
||||
|
||||
for( iString = 0; iString < aanXY.size(); iString++ )
|
||||
{
|
||||
std::vector<int> &anString = aanXY[iString];
|
||||
size_t nSSize = anString.size();
|
||||
|
||||
if( anString[nSSize-2] == x1
|
||||
&& anString[nSSize-1] == y1 )
|
||||
{
|
||||
int nTemp;
|
||||
|
||||
nTemp = x2;
|
||||
x2 = x1;
|
||||
x1 = nTemp;
|
||||
|
||||
nTemp = y2;
|
||||
y2 = y1;
|
||||
y1 = nTemp;
|
||||
}
|
||||
|
||||
if( anString[nSSize-2] == x2
|
||||
&& anString[nSSize-1] == y2 )
|
||||
{
|
||||
// We are going to add a segment, but should we just extend
|
||||
// an existing segment already going in the right direction?
|
||||
|
||||
int nLastLen = MAX(ABS(anString[nSSize-4]-anString[nSSize-2]),
|
||||
ABS(anString[nSSize-3]-anString[nSSize-1]));
|
||||
|
||||
if( nSSize >= 4
|
||||
&& (anString[nSSize-4] - anString[nSSize-2]
|
||||
== (anString[nSSize-2] - x1)*nLastLen)
|
||||
&& (anString[nSSize-3] - anString[nSSize-1]
|
||||
== (anString[nSSize-1] - y1)*nLastLen) )
|
||||
{
|
||||
anString.pop_back();
|
||||
anString.pop_back();
|
||||
}
|
||||
|
||||
anString.push_back( x1 );
|
||||
anString.push_back( y1 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create a new string. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
size_t nSize = aanXY.size();
|
||||
aanXY.resize(nSize + 1);
|
||||
std::vector<int> &anString = aanXY[nSize];
|
||||
|
||||
anString.push_back( x1 );
|
||||
anString.push_back( y1 );
|
||||
anString.push_back( x2 );
|
||||
anString.push_back( y2 );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* End of RPolygon */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
/************************************************************************/
|
||||
/* AddEdges() */
|
||||
/* */
|
||||
/* Examine one pixel and compare to its neighbour above */
|
||||
/* (previous) and right. If they are different polygon ids */
|
||||
/* then add the pixel edge to this polygon and the one on the */
|
||||
/* other side of the edge. */
|
||||
/************************************************************************/
|
||||
|
||||
static void AddEdges( GInt32 *panThisLineId, GInt32 *panLastLineId,
|
||||
GInt32 *panPolyIdMap, GInt32 *panPolyValue,
|
||||
RPolygon **papoPoly, int iX, int iY )
|
||||
|
||||
{
|
||||
int nThisId = panThisLineId[iX];
|
||||
int nRightId = panThisLineId[iX+1];
|
||||
int nPreviousId = panLastLineId[iX];
|
||||
int iXReal = iX - 1;
|
||||
|
||||
if( nThisId != -1 )
|
||||
nThisId = panPolyIdMap[nThisId];
|
||||
if( nRightId != -1 )
|
||||
nRightId = panPolyIdMap[nRightId];
|
||||
if( nPreviousId != -1 )
|
||||
nPreviousId = panPolyIdMap[nPreviousId];
|
||||
|
||||
if( nThisId != nPreviousId )
|
||||
{
|
||||
if( nThisId != -1 )
|
||||
{
|
||||
if( papoPoly[nThisId] == NULL )
|
||||
papoPoly[nThisId] = new RPolygon( panPolyValue[nThisId] );
|
||||
|
||||
papoPoly[nThisId]->AddSegment( iXReal, iY, iXReal+1, iY );
|
||||
}
|
||||
if( nPreviousId != -1 )
|
||||
{
|
||||
if( papoPoly[nPreviousId] == NULL )
|
||||
papoPoly[nPreviousId] = new RPolygon(panPolyValue[nPreviousId]);
|
||||
|
||||
papoPoly[nPreviousId]->AddSegment( iXReal, iY, iXReal+1, iY );
|
||||
}
|
||||
}
|
||||
|
||||
if( nThisId != nRightId )
|
||||
{
|
||||
if( nThisId != -1 )
|
||||
{
|
||||
if( papoPoly[nThisId] == NULL )
|
||||
papoPoly[nThisId] = new RPolygon(panPolyValue[nThisId]);
|
||||
|
||||
papoPoly[nThisId]->AddSegment( iXReal+1, iY, iXReal+1, iY+1 );
|
||||
}
|
||||
|
||||
if( nRightId != -1 )
|
||||
{
|
||||
if( papoPoly[nRightId] == NULL )
|
||||
papoPoly[nRightId] = new RPolygon(panPolyValue[nRightId]);
|
||||
|
||||
papoPoly[nRightId]->AddSegment( iXReal+1, iY, iXReal+1, iY+1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* EmitPolygonToLayer() */
|
||||
/************************************************************************/
|
||||
|
||||
static CPLErr
|
||||
EmitPolygonToLayer( OGRLayerH hOutLayer, int iPixValField,
|
||||
RPolygon *poRPoly, double *padfGeoTransform )
|
||||
|
||||
{
|
||||
OGRFeatureH hFeat;
|
||||
OGRGeometryH hPolygon;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Turn bits of lines into coherent rings. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poRPoly->Coalesce();
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create the polygon geometry. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
size_t iString;
|
||||
|
||||
hPolygon = OGR_G_CreateGeometry( wkbPolygon );
|
||||
|
||||
for( iString = 0; iString < poRPoly->aanXY.size(); iString++ )
|
||||
{
|
||||
std::vector<int> &anString = poRPoly->aanXY[iString];
|
||||
OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing );
|
||||
|
||||
int iVert;
|
||||
|
||||
// we go last to first to ensure the linestring is allocated to
|
||||
// the proper size on the first try.
|
||||
for( iVert = anString.size()/2 - 1; iVert >= 0; iVert-- )
|
||||
{
|
||||
double dfX, dfY;
|
||||
int nPixelX, nPixelY;
|
||||
|
||||
nPixelX = anString[iVert*2];
|
||||
nPixelY = anString[iVert*2+1];
|
||||
|
||||
dfX = padfGeoTransform[0]
|
||||
+ nPixelX * padfGeoTransform[1]
|
||||
+ nPixelY * padfGeoTransform[2];
|
||||
dfY = padfGeoTransform[3]
|
||||
+ nPixelX * padfGeoTransform[4]
|
||||
+ nPixelY * padfGeoTransform[5];
|
||||
|
||||
OGR_G_SetPoint_2D( hRing, iVert, dfX, dfY );
|
||||
}
|
||||
|
||||
OGR_G_AddGeometryDirectly( hPolygon, hRing );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create the feature object. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
hFeat = OGR_F_Create( OGR_L_GetLayerDefn( hOutLayer ) );
|
||||
|
||||
OGR_F_SetGeometryDirectly( hFeat, hPolygon );
|
||||
|
||||
if( iPixValField >= 0 )
|
||||
OGR_F_SetFieldInteger( hFeat, iPixValField, poRPoly->nPolyValue );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Write the to the layer. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLErr eErr = CE_None;
|
||||
|
||||
if( OGR_L_CreateFeature( hOutLayer, hFeat ) != OGRERR_NONE )
|
||||
eErr = CE_Failure;
|
||||
|
||||
OGR_F_Destroy( hFeat );
|
||||
|
||||
return eErr;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GPMaskImageData() */
|
||||
/* */
|
||||
/* Mask out image pixels to a special nodata value if the mask */
|
||||
/* band is zero. */
|
||||
/************************************************************************/
|
||||
|
||||
static CPLErr
|
||||
GPMaskImageData( GDALRasterBandH hMaskBand, GByte* pabyMaskLine, int iY, int nXSize,
|
||||
GInt32 *panImageLine )
|
||||
|
||||
{
|
||||
CPLErr eErr;
|
||||
|
||||
eErr = GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1,
|
||||
pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0 );
|
||||
if( eErr == CE_None )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < nXSize; i++ )
|
||||
{
|
||||
if( pabyMaskLine[i] == 0 )
|
||||
panImageLine[i] = GP_NODATA_MARKER;
|
||||
}
|
||||
}
|
||||
|
||||
return eErr;
|
||||
}
|
||||
#endif // OGR_ENABLED
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALPolygonize() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Create polygon coverage from raster data.
|
||||
*
|
||||
* This function creates vector polygons for all connected regions of pixels in
|
||||
* the raster sharing a common pixel value. Optionally each polygon may be
|
||||
* labelled with the pixel value in an attribute. Optionally a mask band
|
||||
* can be provided to determine which pixels are eligible for processing.
|
||||
*
|
||||
* Note that currently the source pixel band values are read into a
|
||||
* signed 32bit integer buffer (Int32), so floating point or complex
|
||||
* bands will be implicitly truncated before processing. If you want to use a
|
||||
* version using 32bit float buffers, see GDALFPolygonize() at fpolygonize.cpp.
|
||||
*
|
||||
* Polygon features will be created on the output layer, with polygon
|
||||
* geometries representing the polygons. The polygon geometries will be
|
||||
* in the georeferenced coordinate system of the image (based on the
|
||||
* geotransform of the source dataset). It is acceptable for the output
|
||||
* layer to already have features. Note that GDALPolygonize() does not
|
||||
* set the coordinate system on the output layer. Application code should
|
||||
* do this when the layer is created, presumably matching the raster
|
||||
* coordinate system.
|
||||
*
|
||||
* The algorithm used attempts to minimize memory use so that very large
|
||||
* rasters can be processed. However, if the raster has many polygons
|
||||
* or very large/complex polygons, the memory use for holding polygon
|
||||
* enumerations and active polygon geometries may grow to be quite large.
|
||||
*
|
||||
* The algorithm will generally produce very dense polygon geometries, with
|
||||
* edges that follow exactly on pixel boundaries for all non-interior pixels.
|
||||
* For non-thematic raster data (such as satellite images) the result will
|
||||
* essentially be one small polygon per pixel, and memory and output layer
|
||||
* sizes will be substantial. The algorithm is primarily intended for
|
||||
* relatively simple thematic imagery, masks, and classification results.
|
||||
*
|
||||
* @param hSrcBand the source raster band to be processed.
|
||||
* @param hMaskBand an optional mask band. All pixels in the mask band with a
|
||||
* value other than zero will be considered suitable for collection as
|
||||
* polygons.
|
||||
* @param hOutLayer the vector feature layer to which the polygons should
|
||||
* be written.
|
||||
* @param iPixValField the attribute field index indicating the feature
|
||||
* attribute into which the pixel value of the polygon should be written.
|
||||
* @param papszOptions a name/value list of additional options
|
||||
* <dl>
|
||||
* <dt>"8CONNECTED":</dt> May be set to "8" to use 8 connectedness.
|
||||
* Otherwise 4 connectedness will be applied to the algorithm
|
||||
* </dl>
|
||||
* @param pfnProgress callback for reporting algorithm progress matching the
|
||||
* GDALProgressFunc() semantics. May be NULL.
|
||||
* @param pProgressArg callback argument passed to pfnProgress.
|
||||
*
|
||||
* @return CE_None on success or CE_Failure on a failure.
|
||||
*/
|
||||
|
||||
CPLErr CPL_STDCALL
|
||||
GDALPolygonize( GDALRasterBandH hSrcBand,
|
||||
GDALRasterBandH hMaskBand,
|
||||
OGRLayerH hOutLayer, int iPixValField,
|
||||
char **papszOptions,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg )
|
||||
|
||||
{
|
||||
#ifndef OGR_ENABLED
|
||||
CPLError(CE_Failure, CPLE_NotSupported, "GDALPolygonize() unimplemented in a non OGR build");
|
||||
return CE_Failure;
|
||||
#else
|
||||
VALIDATE_POINTER1( hSrcBand, "GDALPolygonize", CE_Failure );
|
||||
VALIDATE_POINTER1( hOutLayer, "GDALPolygonize", CE_Failure );
|
||||
|
||||
if( pfnProgress == NULL )
|
||||
pfnProgress = GDALDummyProgress;
|
||||
|
||||
int nConnectedness = CSLFetchNameValue( papszOptions, "8CONNECTED" ) ? 8 : 4;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Confirm our output layer will support feature creation. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( !OGR_L_TestCapability( hOutLayer, OLCSequentialWrite ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Output feature layer does not appear to support creation\n"
|
||||
"of features in GDALPolygonize()." );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Allocate working buffers. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLErr eErr = CE_None;
|
||||
int nXSize = GDALGetRasterBandXSize( hSrcBand );
|
||||
int nYSize = GDALGetRasterBandYSize( hSrcBand );
|
||||
GInt32 *panLastLineVal = (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
|
||||
GInt32 *panThisLineVal = (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
|
||||
GInt32 *panLastLineId = (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
|
||||
GInt32 *panThisLineId = (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
|
||||
GByte *pabyMaskLine = (hMaskBand != NULL) ? (GByte *) VSIMalloc(nXSize) : NULL;
|
||||
if (panLastLineVal == NULL || panThisLineVal == NULL ||
|
||||
panLastLineId == NULL || panThisLineId == NULL ||
|
||||
(hMaskBand != NULL && pabyMaskLine == NULL))
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_OutOfMemory,
|
||||
"Could not allocate enough memory for temporary buffers");
|
||||
CPLFree( panThisLineId );
|
||||
CPLFree( panLastLineId );
|
||||
CPLFree( panThisLineVal );
|
||||
CPLFree( panLastLineVal );
|
||||
CPLFree( pabyMaskLine );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Get the geotransform, if there is one, so we can convert the */
|
||||
/* vectors into georeferenced coordinates. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GDALDatasetH hSrcDS = GDALGetBandDataset( hSrcBand );
|
||||
double adfGeoTransform[6] = { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 };
|
||||
|
||||
if( hSrcDS )
|
||||
GDALGetGeoTransform( hSrcDS, adfGeoTransform );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* The first pass over the raster is only used to build up the */
|
||||
/* polygon id map so we will know in advance what polygons are */
|
||||
/* what on the second pass. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int iY;
|
||||
GDALRasterPolygonEnumerator oFirstEnum(nConnectedness);
|
||||
|
||||
for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
|
||||
{
|
||||
eErr = GDALRasterIO(
|
||||
hSrcBand,
|
||||
GF_Read, 0, iY, nXSize, 1,
|
||||
panThisLineVal, nXSize, 1, GDT_Int32, 0, 0 );
|
||||
|
||||
if( eErr == CE_None && hMaskBand != NULL )
|
||||
eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize, panThisLineVal );
|
||||
|
||||
if( iY == 0 )
|
||||
oFirstEnum.ProcessLine(
|
||||
NULL, panThisLineVal, NULL, panThisLineId, nXSize );
|
||||
else
|
||||
oFirstEnum.ProcessLine(
|
||||
panLastLineVal, panThisLineVal,
|
||||
panLastLineId, panThisLineId,
|
||||
nXSize );
|
||||
|
||||
// swap lines
|
||||
GInt32 *panTmp = panLastLineVal;
|
||||
panLastLineVal = panThisLineVal;
|
||||
panThisLineVal = panTmp;
|
||||
|
||||
panTmp = panThisLineId;
|
||||
panThisLineId = panLastLineId;
|
||||
panLastLineId = panTmp;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Report progress, and support interrupts. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( eErr == CE_None
|
||||
&& !pfnProgress( 0.10 * ((iY+1) / (double) nYSize),
|
||||
"", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
eErr = CE_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Make a pass through the maps, ensuring every polygon id */
|
||||
/* points to the final id it should use, not an intermediate */
|
||||
/* value. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
oFirstEnum.CompleteMerges();
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Initialize ids to -1 to serve as a nodata value for the */
|
||||
/* previous line, and past the beginning and end of the */
|
||||
/* scanlines. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int iX;
|
||||
|
||||
panThisLineId[0] = -1;
|
||||
panThisLineId[nXSize+1] = -1;
|
||||
|
||||
for( iX = 0; iX < nXSize+2; iX++ )
|
||||
panLastLineId[iX] = -1;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* We will use a new enumerator for the second pass primariliy */
|
||||
/* so we can preserve the first pass map. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GDALRasterPolygonEnumerator oSecondEnum(nConnectedness);
|
||||
RPolygon **papoPoly = (RPolygon **)
|
||||
CPLCalloc(sizeof(RPolygon*),oFirstEnum.nNextPolygonId);
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Second pass during which we will actually collect polygon */
|
||||
/* edges as geometries. */
|
||||
/* ==================================================================== */
|
||||
for( iY = 0; eErr == CE_None && iY < nYSize+1; iY++ )
|
||||
{
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read the image data. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( iY < nYSize )
|
||||
{
|
||||
eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1,
|
||||
panThisLineVal, nXSize, 1, GDT_Int32, 0, 0 );
|
||||
|
||||
if( eErr == CE_None && hMaskBand != NULL )
|
||||
eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize, panThisLineVal );
|
||||
}
|
||||
|
||||
if( eErr != CE_None )
|
||||
continue;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Determine what polygon the various pixels belong to (redoing */
|
||||
/* the same thing done in the first pass above). */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( iY == nYSize )
|
||||
{
|
||||
for( iX = 0; iX < nXSize+2; iX++ )
|
||||
panThisLineId[iX] = -1;
|
||||
}
|
||||
else if( iY == 0 )
|
||||
oSecondEnum.ProcessLine(
|
||||
NULL, panThisLineVal, NULL, panThisLineId+1, nXSize );
|
||||
else
|
||||
oSecondEnum.ProcessLine(
|
||||
panLastLineVal, panThisLineVal,
|
||||
panLastLineId+1, panThisLineId+1,
|
||||
nXSize );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Add polygon edges to our polygon list for the pixel */
|
||||
/* boundaries within and above this line. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( iX = 0; iX < nXSize+1; iX++ )
|
||||
{
|
||||
AddEdges( panThisLineId, panLastLineId,
|
||||
oFirstEnum.panPolyIdMap, oFirstEnum.panPolyValue,
|
||||
papoPoly, iX, iY );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Periodically we scan out polygons and write out those that */
|
||||
/* haven't been added to on the last line as we can be sure */
|
||||
/* they are complete. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( iY % 8 == 7 )
|
||||
{
|
||||
for( iX = 0;
|
||||
eErr == CE_None && iX < oSecondEnum.nNextPolygonId;
|
||||
iX++ )
|
||||
{
|
||||
if( papoPoly[iX] && papoPoly[iX]->nLastLineUpdated < iY-1 )
|
||||
{
|
||||
eErr =
|
||||
EmitPolygonToLayer( hOutLayer, iPixValField,
|
||||
papoPoly[iX], adfGeoTransform );
|
||||
|
||||
delete papoPoly[iX];
|
||||
papoPoly[iX] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Swap pixel value, and polygon id lines to be ready for the */
|
||||
/* next line. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GInt32 *panTmp = panLastLineVal;
|
||||
panLastLineVal = panThisLineVal;
|
||||
panThisLineVal = panTmp;
|
||||
|
||||
panTmp = panThisLineId;
|
||||
panThisLineId = panLastLineId;
|
||||
panLastLineId = panTmp;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Report progress, and support interrupts. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( eErr == CE_None
|
||||
&& !pfnProgress( 0.10 + 0.90 * ((iY+1) / (double) nYSize),
|
||||
"", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
eErr = CE_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Make a cleanup pass for all unflushed polygons. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( iX = 0; eErr == CE_None && iX < oSecondEnum.nNextPolygonId; iX++ )
|
||||
{
|
||||
if( papoPoly[iX] )
|
||||
{
|
||||
eErr =
|
||||
EmitPolygonToLayer( hOutLayer, iPixValField,
|
||||
papoPoly[iX], adfGeoTransform );
|
||||
|
||||
delete papoPoly[iX];
|
||||
papoPoly[iX] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Cleanup */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLFree( panThisLineId );
|
||||
CPLFree( panLastLineId );
|
||||
CPLFree( panThisLineVal );
|
||||
CPLFree( panLastLineVal );
|
||||
CPLFree( pabyMaskLine );
|
||||
CPLFree( papoPoly );
|
||||
|
||||
return eErr;
|
||||
#endif // OGR_ENABLED
|
||||
}
|
||||
|
||||
886
bazaar/plugin/gdal/alg/rasterfill.cpp
Normal file
886
bazaar/plugin/gdal/alg/rasterfill.cpp
Normal file
|
|
@ -0,0 +1,886 @@
|
|||
/******************************************************************************
|
||||
* $Id: rasterfill.cpp 28342 2015-01-22 12:31:07Z rouault $
|
||||
*
|
||||
* Project: GDAL
|
||||
* Purpose: Interpolate in nodata areas.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2008, Frank Warmerdam
|
||||
* Copyright (c) 2015, Sean Gillies <sean@mapbox.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
***************************************************************************/
|
||||
|
||||
#include "gdal_alg.h"
|
||||
#include "cpl_conv.h"
|
||||
#include "cpl_string.h"
|
||||
|
||||
CPL_CVSID("$Id: rasterfill.cpp 28342 2015-01-22 12:31:07Z rouault $");
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALFilterLine() */
|
||||
/* */
|
||||
/* Apply 3x3 filtering one one scanline with masking for which */
|
||||
/* pixels are to be interpolated (ThisFMask) and which window */
|
||||
/* pixels are valid to include in the interpolation (TMask). */
|
||||
/************************************************************************/
|
||||
|
||||
static void
|
||||
GDALFilterLine( float *pafLastLine, float *pafThisLine, float *pafNextLine,
|
||||
float *pafOutLine,
|
||||
GByte *pabyLastTMask, GByte *pabyThisTMask, GByte*pabyNextTMask,
|
||||
GByte *pabyThisFMask, int nXSize )
|
||||
|
||||
{
|
||||
int iX;
|
||||
|
||||
for( iX = 0; iX < nXSize; iX++ )
|
||||
{
|
||||
if( !pabyThisFMask[iX] )
|
||||
{
|
||||
pafOutLine[iX] = pafThisLine[iX];
|
||||
continue;
|
||||
}
|
||||
|
||||
CPLAssert( pabyThisTMask[iX] );
|
||||
|
||||
double dfValSum = 0.0;
|
||||
double dfWeightSum = 0.0;
|
||||
|
||||
// Previous line
|
||||
if( pafLastLine != NULL )
|
||||
{
|
||||
if( iX > 0 && pabyLastTMask[iX-1] )
|
||||
{
|
||||
dfValSum += pafLastLine[iX-1];
|
||||
dfWeightSum += 1.0;
|
||||
}
|
||||
if( pabyLastTMask[iX] )
|
||||
{
|
||||
dfValSum += pafLastLine[iX];
|
||||
dfWeightSum += 1.0;
|
||||
}
|
||||
if( iX < nXSize-1 && pabyLastTMask[iX+1] )
|
||||
{
|
||||
dfValSum += pafLastLine[iX+1];
|
||||
dfWeightSum += 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Current Line
|
||||
if( iX > 0 && pabyThisTMask[iX-1] )
|
||||
{
|
||||
dfValSum += pafThisLine[iX-1];
|
||||
dfWeightSum += 1.0;
|
||||
}
|
||||
if( pabyThisTMask[iX] )
|
||||
{
|
||||
dfValSum += pafThisLine[iX];
|
||||
dfWeightSum += 1.0;
|
||||
}
|
||||
if( iX < nXSize-1 && pabyThisTMask[iX+1] )
|
||||
{
|
||||
dfValSum += pafThisLine[iX+1];
|
||||
dfWeightSum += 1.0;
|
||||
}
|
||||
|
||||
// Next line
|
||||
if( pafNextLine != NULL )
|
||||
{
|
||||
if( iX > 0 && pabyNextTMask[iX-1] )
|
||||
{
|
||||
dfValSum += pafNextLine[iX-1];
|
||||
dfWeightSum += 1.0;
|
||||
}
|
||||
if( pabyNextTMask[iX] )
|
||||
{
|
||||
dfValSum += pafNextLine[iX];
|
||||
dfWeightSum += 1.0;
|
||||
}
|
||||
if( iX < nXSize-1 && pabyNextTMask[iX+1] )
|
||||
{
|
||||
dfValSum += pafNextLine[iX+1];
|
||||
dfWeightSum += 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
pafOutLine[iX] = (float) (dfValSum / dfWeightSum);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALMultiFilter() */
|
||||
/* */
|
||||
/* Apply multiple iterations of a 3x3 smoothing filter over a */
|
||||
/* band with masking controlling what pixels should be */
|
||||
/* filtered (FiltMaskBand non zero) and which pixels can be */
|
||||
/* considered valid contributors to the filter */
|
||||
/* (TargetMaskBand non zero). */
|
||||
/* */
|
||||
/* This implementation attempts to apply many iterations in */
|
||||
/* one IO pass by managing the filtering over a rolling buffer */
|
||||
/* of nIternations+2 scanlines. While possibly clever this */
|
||||
/* makes the algorithm implementation largely */
|
||||
/* incomprehensible. */
|
||||
/************************************************************************/
|
||||
|
||||
static CPLErr
|
||||
GDALMultiFilter( GDALRasterBandH hTargetBand,
|
||||
GDALRasterBandH hTargetMaskBand,
|
||||
GDALRasterBandH hFiltMaskBand,
|
||||
int nIterations,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg )
|
||||
|
||||
{
|
||||
float *paf3PassLineBuf;
|
||||
GByte *pabyTMaskBuf;
|
||||
GByte *pabyFMaskBuf;
|
||||
float *pafThisPass, *pafLastPass, *pafSLastPass;
|
||||
|
||||
int nBufLines = nIterations + 2;
|
||||
int iPassCounter = 0;
|
||||
int nNewLine; // the line being loaded this time (zero based scanline)
|
||||
int nXSize = GDALGetRasterBandXSize( hTargetBand );
|
||||
int nYSize = GDALGetRasterBandYSize( hTargetBand );
|
||||
CPLErr eErr = CE_None;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Report starting progress value. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( !pfnProgress( 0.0, "Smoothing Filter...", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Allocate rotating buffers. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
pabyTMaskBuf = (GByte *) VSIMalloc2(nXSize, nBufLines);
|
||||
pabyFMaskBuf = (GByte *) VSIMalloc2(nXSize, nBufLines);
|
||||
|
||||
paf3PassLineBuf = (float *) VSIMalloc3(nXSize, nBufLines, 3 * sizeof(float));
|
||||
if (pabyTMaskBuf == NULL || pabyFMaskBuf == NULL || paf3PassLineBuf == NULL)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_OutOfMemory,
|
||||
"Could not allocate enough memory for temporary buffers");
|
||||
eErr = CE_Failure;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Process rotating buffers. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( nNewLine = 0;
|
||||
eErr == CE_None && nNewLine < nYSize+nIterations;
|
||||
nNewLine++ )
|
||||
{
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Rotate pass buffers. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
iPassCounter = (iPassCounter + 1) % 3;
|
||||
|
||||
pafSLastPass = paf3PassLineBuf
|
||||
+ ((iPassCounter+0)%3) * nXSize*nBufLines;
|
||||
pafLastPass = paf3PassLineBuf
|
||||
+ ((iPassCounter+1)%3) * nXSize*nBufLines;
|
||||
pafThisPass = paf3PassLineBuf
|
||||
+ ((iPassCounter+2)%3) * nXSize*nBufLines;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Where does the new line go in the rotating buffer? */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int iBufOffset = nNewLine % nBufLines;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read the new data line if it is't off the bottom of the */
|
||||
/* image. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( nNewLine < nYSize )
|
||||
{
|
||||
eErr =
|
||||
GDALRasterIO( hTargetMaskBand, GF_Read,
|
||||
0, nNewLine, nXSize, 1,
|
||||
pabyTMaskBuf + nXSize * iBufOffset, nXSize, 1,
|
||||
GDT_Byte, 0, 0 );
|
||||
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
eErr =
|
||||
GDALRasterIO( hFiltMaskBand, GF_Read,
|
||||
0, nNewLine, nXSize, 1,
|
||||
pabyFMaskBuf + nXSize * iBufOffset, nXSize, 1,
|
||||
GDT_Byte, 0, 0 );
|
||||
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
eErr =
|
||||
GDALRasterIO( hTargetBand, GF_Read,
|
||||
0, nNewLine, nXSize, 1,
|
||||
pafThisPass + nXSize * iBufOffset, nXSize, 1,
|
||||
GDT_Float32, 0, 0 );
|
||||
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Loop over the loaded data, applying the filter to all loaded */
|
||||
/* lines with neighbours. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int iFLine;
|
||||
|
||||
for( iFLine = nNewLine-1;
|
||||
eErr == CE_None && iFLine >= nNewLine-nIterations;
|
||||
iFLine-- )
|
||||
{
|
||||
int iLastOffset, iThisOffset, iNextOffset;
|
||||
|
||||
iLastOffset = (iFLine-1) % nBufLines;
|
||||
iThisOffset = (iFLine ) % nBufLines;
|
||||
iNextOffset = (iFLine+1) % nBufLines;
|
||||
|
||||
// default to preserving the old value.
|
||||
if( iFLine >= 0 )
|
||||
memcpy( pafThisPass + iThisOffset * nXSize,
|
||||
pafLastPass + iThisOffset * nXSize,
|
||||
sizeof(float) * nXSize );
|
||||
|
||||
// currently this skips the first and last line. Eventually
|
||||
// we will enable these too. TODO
|
||||
if( iFLine < 1 || iFLine >= nYSize-1 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
GDALFilterLine(
|
||||
pafSLastPass + iLastOffset * nXSize,
|
||||
pafLastPass + iThisOffset * nXSize,
|
||||
pafThisPass + iNextOffset * nXSize,
|
||||
pafThisPass + iThisOffset * nXSize,
|
||||
pabyTMaskBuf + iLastOffset * nXSize,
|
||||
pabyTMaskBuf + iThisOffset * nXSize,
|
||||
pabyTMaskBuf + iNextOffset * nXSize,
|
||||
pabyFMaskBuf + iThisOffset * nXSize,
|
||||
nXSize );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Write out the top data line that will be rolling out of our */
|
||||
/* buffer. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int iLineToSave = nNewLine - nIterations;
|
||||
|
||||
if( iLineToSave >= 0 && eErr == CE_None )
|
||||
{
|
||||
iBufOffset = iLineToSave % nBufLines;
|
||||
|
||||
eErr =
|
||||
GDALRasterIO( hTargetBand, GF_Write,
|
||||
0, iLineToSave, nXSize, 1,
|
||||
pafThisPass + nXSize * iBufOffset, nXSize, 1,
|
||||
GDT_Float32, 0, 0 );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Report progress. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( eErr == CE_None
|
||||
&& !pfnProgress( (nNewLine+1) / (double) (nYSize+nIterations),
|
||||
"Smoothing Filter...", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
eErr = CE_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Cleanup */
|
||||
/* -------------------------------------------------------------------- */
|
||||
end:
|
||||
CPLFree( pabyTMaskBuf );
|
||||
CPLFree( pabyFMaskBuf );
|
||||
CPLFree( paf3PassLineBuf );
|
||||
|
||||
return eErr;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* QUAD_CHECK() */
|
||||
/* */
|
||||
/* macro for checking whether a point is nearer than the */
|
||||
/* existing closest point. */
|
||||
/************************************************************************/
|
||||
#define QUAD_CHECK(quad_dist, quad_value, \
|
||||
target_x, target_y, origin_x, origin_y, target_value ) \
|
||||
\
|
||||
if( quad_value != nNoDataVal ) \
|
||||
{ \
|
||||
double dfDx = (double)target_x - (double)origin_x; \
|
||||
double dfDy = (double)target_y - (double)origin_y; \
|
||||
double dfDistSq = dfDx * dfDx + dfDy * dfDy; \
|
||||
\
|
||||
if( dfDistSq < quad_dist*quad_dist ) \
|
||||
{ \
|
||||
CPLAssert( dfDistSq > 0.0 ); \
|
||||
quad_dist = sqrt(dfDistSq); \
|
||||
quad_value = target_value; \
|
||||
} \
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALFillNodata() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Fill selected raster regions by interpolation from the edges.
|
||||
*
|
||||
* This algorithm will interpolate values for all designated
|
||||
* nodata pixels (marked by zeros in hMaskBand). For each pixel
|
||||
* a four direction conic search is done to find values to interpolate
|
||||
* from (using inverse distance weighting). Once all values are
|
||||
* interpolated, zero or more smoothing iterations (3x3 average
|
||||
* filters on interpolated pixels) are applied to smooth out
|
||||
* artifacts.
|
||||
*
|
||||
* This algorithm is generally suitable for interpolating missing
|
||||
* regions of fairly continuously varying rasters (such as elevation
|
||||
* models for instance). It is also suitable for filling small holes
|
||||
* and cracks in more irregularly varying images (like airphotos). It
|
||||
* is generally not so great for interpolating a raster from sparse
|
||||
* point data - see the algorithms defined in gdal_grid.h for that case.
|
||||
*
|
||||
* @param hTargetBand the raster band to be modified in place.
|
||||
* @param hMaskBand a mask band indicating pixels to be interpolated (zero valued
|
||||
* @param dfMaxSearchDist the maximum number of pixels to search in all
|
||||
* directions to find values to interpolate from.
|
||||
* @param bDeprecatedOption unused argument, should be zero.
|
||||
* @param nSmoothingIterations the number of 3x3 smoothing filter passes to
|
||||
* run (0 or more).
|
||||
* @param papszOptions additional name=value options in a string list (the
|
||||
* temporary file driver can be specified like TEMP_FILE_DRIVER=MEM).
|
||||
* @param pfnProgress the progress function to report completion.
|
||||
* @param pProgressArg callback data for progress function.
|
||||
*
|
||||
* @return CE_None on success or CE_Failure if something goes wrong.
|
||||
*/
|
||||
|
||||
CPLErr CPL_STDCALL
|
||||
GDALFillNodata( GDALRasterBandH hTargetBand,
|
||||
GDALRasterBandH hMaskBand,
|
||||
double dfMaxSearchDist,
|
||||
int bDeprecatedOption,
|
||||
int nSmoothingIterations,
|
||||
char **papszOptions,
|
||||
GDALProgressFunc pfnProgress,
|
||||
void * pProgressArg )
|
||||
|
||||
{
|
||||
VALIDATE_POINTER1( hTargetBand, "GDALFillNodata", CE_Failure );
|
||||
|
||||
int nXSize = GDALGetRasterBandXSize( hTargetBand );
|
||||
int nYSize = GDALGetRasterBandYSize( hTargetBand );
|
||||
CPLErr eErr = CE_None;
|
||||
|
||||
// Special "x" pixel values identifying pixels as special.
|
||||
GUInt32 nNoDataVal;
|
||||
GDALDataType eType;
|
||||
|
||||
if( dfMaxSearchDist == 0.0 )
|
||||
dfMaxSearchDist = MAX(nXSize,nYSize) + 1;
|
||||
|
||||
int nMaxSearchDist = (int) floor(dfMaxSearchDist);
|
||||
|
||||
if( nXSize > 65533 || nYSize > 65533 )
|
||||
{
|
||||
eType = GDT_UInt32;
|
||||
nNoDataVal = 4000002;
|
||||
}
|
||||
else
|
||||
{
|
||||
eType = GDT_UInt16;
|
||||
nNoDataVal = 65535;
|
||||
}
|
||||
|
||||
if( hMaskBand == NULL )
|
||||
hMaskBand = GDALGetMaskBand( hTargetBand );
|
||||
|
||||
/* If there are smoothing iterations, reserve 10% of the progress for them */
|
||||
double dfProgressRatio = (nSmoothingIterations > 0) ? 0.9 : 1.0;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Initialize progress counter. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( pfnProgress == NULL )
|
||||
pfnProgress = GDALDummyProgress;
|
||||
|
||||
if( !pfnProgress( 0.0, "Filling...", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Determine format driver for temp work files. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CPLString osTmpFileDriver = CSLFetchNameValueDef(
|
||||
papszOptions, "TEMP_FILE_DRIVER", "GTiff");
|
||||
GDALDriverH hDriver = GDALGetDriverByName((const char *) osTmpFileDriver);
|
||||
|
||||
if (hDriver == NULL)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"Given driver is not registered");
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, NULL) == NULL)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"Given driver is incapable of creating temp work files");
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
char **papszWorkFileOptions = NULL;
|
||||
if (osTmpFileDriver == "GTiff") {
|
||||
papszWorkFileOptions = CSLSetNameValue(
|
||||
papszWorkFileOptions, "COMPRESS", "LZW");
|
||||
papszWorkFileOptions = CSLSetNameValue(
|
||||
papszWorkFileOptions, "BIGTIFF", "IF_SAFER");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create a work file to hold the Y "last value" indices. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GDALDatasetH hYDS;
|
||||
GDALRasterBandH hYBand;
|
||||
|
||||
CPLString osTmpFile = CPLGenerateTempFilename("");
|
||||
CPLString osYTmpFile = osTmpFile + "fill_y_work.tif";
|
||||
|
||||
hYDS = GDALCreate( hDriver, osYTmpFile, nXSize, nYSize, 1,
|
||||
eType, (char **) papszWorkFileOptions );
|
||||
|
||||
if ( hYDS == NULL )
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"Could not create Y index work file. Check driver capabilities.");
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
hYBand = GDALGetRasterBand( hYDS, 1 );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create a work file to hold the pixel value associated with */
|
||||
/* the "last xy value" pixel. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GDALDatasetH hValDS;
|
||||
GDALRasterBandH hValBand;
|
||||
CPLString osValTmpFile = osTmpFile + "fill_val_work.tif";
|
||||
|
||||
hValDS = GDALCreate( hDriver, osValTmpFile, nXSize, nYSize, 1,
|
||||
GDALGetRasterDataType( hTargetBand ),
|
||||
(char **) papszWorkFileOptions );
|
||||
|
||||
if ( hValDS == NULL )
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"Could not create XY value work file. Check driver capabilities.");
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
hValBand = GDALGetRasterBand( hValDS, 1 );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create a mask file to make it clear what pixels can be filtered */
|
||||
/* on the filtering pass. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GDALDatasetH hFiltMaskDS;
|
||||
GDALRasterBandH hFiltMaskBand;
|
||||
CPLString osFiltMaskTmpFile = osTmpFile + "fill_filtmask_work.tif";
|
||||
|
||||
hFiltMaskDS =
|
||||
GDALCreate( hDriver, osFiltMaskTmpFile, nXSize, nYSize, 1,
|
||||
GDT_Byte, (char **) papszWorkFileOptions );
|
||||
|
||||
if ( hFiltMaskDS == NULL )
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"Could not create mask work file. Check driver capabilities.");
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
hFiltMaskBand = GDALGetRasterBand( hFiltMaskDS, 1 );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Allocate buffers for last scanline and this scanline. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
GUInt32 *panLastY, *panThisY, *panTopDownY;
|
||||
float *pafLastValue, *pafThisValue, *pafScanline, *pafTopDownValue;
|
||||
GByte *pabyMask, *pabyFiltMask;
|
||||
int iX;
|
||||
int iY;
|
||||
|
||||
panLastY = (GUInt32 *) VSICalloc(nXSize,sizeof(GUInt32));
|
||||
panThisY = (GUInt32 *) VSICalloc(nXSize,sizeof(GUInt32));
|
||||
panTopDownY = (GUInt32 *) VSICalloc(nXSize,sizeof(GUInt32));
|
||||
pafLastValue = (float *) VSICalloc(nXSize,sizeof(float));
|
||||
pafThisValue = (float *) VSICalloc(nXSize,sizeof(float));
|
||||
pafTopDownValue = (float *) VSICalloc(nXSize,sizeof(float));
|
||||
pafScanline = (float *) VSICalloc(nXSize,sizeof(float));
|
||||
pabyMask = (GByte *) VSICalloc(nXSize,1);
|
||||
pabyFiltMask = (GByte *) VSICalloc(nXSize,1);
|
||||
if (panLastY == NULL || panThisY == NULL || panTopDownY == NULL ||
|
||||
pafLastValue == NULL || pafThisValue == NULL || pafTopDownValue == NULL ||
|
||||
pafScanline == NULL || pabyMask == NULL || pabyFiltMask == NULL)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_OutOfMemory,
|
||||
"Could not allocate enough memory for temporary buffers");
|
||||
|
||||
eErr = CE_Failure;
|
||||
goto end;
|
||||
}
|
||||
|
||||
for( iX = 0; iX < nXSize; iX++ )
|
||||
{
|
||||
panLastY[iX] = nNoDataVal;
|
||||
}
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Make first pass from top to bottom collecting the "last */
|
||||
/* known value" for each column and writing it out to the work */
|
||||
/* files. */
|
||||
/* ==================================================================== */
|
||||
|
||||
for( iY = 0; iY < nYSize && eErr == CE_None; iY++ )
|
||||
{
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read data and mask for this line. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
eErr =
|
||||
GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1,
|
||||
pabyMask, nXSize, 1, GDT_Byte, 0, 0 );
|
||||
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
eErr =
|
||||
GDALRasterIO( hTargetBand, GF_Read, 0, iY, nXSize, 1,
|
||||
pafScanline, nXSize, 1, GDT_Float32, 0, 0 );
|
||||
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Figure out the most recent pixel for each column. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
for( iX = 0; iX < nXSize; iX++ )
|
||||
{
|
||||
if( pabyMask[iX] )
|
||||
{
|
||||
pafThisValue[iX] = pafScanline[iX];
|
||||
panThisY[iX] = iY;
|
||||
}
|
||||
else if( iY <= dfMaxSearchDist + panLastY[iX] )
|
||||
{
|
||||
pafThisValue[iX] = pafLastValue[iX];
|
||||
panThisY[iX] = panLastY[iX];
|
||||
}
|
||||
else
|
||||
{
|
||||
panThisY[iX] = nNoDataVal;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Write out best index/value to working files. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
eErr = GDALRasterIO( hYBand, GF_Write, 0, iY, nXSize, 1,
|
||||
panThisY, nXSize, 1, GDT_UInt32, 0, 0 );
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
eErr = GDALRasterIO( hValBand, GF_Write, 0, iY, nXSize, 1,
|
||||
pafThisValue, nXSize, 1, GDT_Float32, 0, 0 );
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Flip this/last buffers. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
{
|
||||
float *pafTmp = pafThisValue;
|
||||
pafThisValue = pafLastValue;
|
||||
pafLastValue = pafTmp;
|
||||
|
||||
GUInt32 *panTmp = panThisY;
|
||||
panThisY = panLastY;
|
||||
panLastY = panTmp;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* report progress. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( eErr == CE_None
|
||||
&& !pfnProgress( dfProgressRatio * (0.5*(iY+1) / (double)nYSize),
|
||||
"Filling...", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
eErr = CE_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Now we will do collect similar this/last information from */
|
||||
/* bottom to top and use it in combination with the top to */
|
||||
/* bottom search info to interpolate. */
|
||||
/* ==================================================================== */
|
||||
for( iY = nYSize-1; iY >= 0 && eErr == CE_None; iY-- )
|
||||
{
|
||||
eErr =
|
||||
GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1,
|
||||
pabyMask, nXSize, 1, GDT_Byte, 0, 0 );
|
||||
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
eErr =
|
||||
GDALRasterIO( hTargetBand, GF_Read, 0, iY, nXSize, 1,
|
||||
pafScanline, nXSize, 1, GDT_Float32, 0, 0 );
|
||||
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Figure out the most recent pixel for each column. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
for( iX = 0; iX < nXSize; iX++ )
|
||||
{
|
||||
if( pabyMask[iX] )
|
||||
{
|
||||
pafThisValue[iX] = pafScanline[iX];
|
||||
panThisY[iX] = iY;
|
||||
}
|
||||
else if( panLastY[iX] - iY <= dfMaxSearchDist )
|
||||
{
|
||||
pafThisValue[iX] = pafLastValue[iX];
|
||||
panThisY[iX] = panLastY[iX];
|
||||
}
|
||||
else
|
||||
{
|
||||
panThisY[iX] = nNoDataVal;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Load the last y and corresponding value from the top down pass. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
eErr =
|
||||
GDALRasterIO( hYBand, GF_Read, 0, iY, nXSize, 1,
|
||||
panTopDownY, nXSize, 1, GDT_UInt32, 0, 0 );
|
||||
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
eErr =
|
||||
GDALRasterIO( hValBand, GF_Read, 0, iY, nXSize, 1,
|
||||
pafTopDownValue, nXSize, 1, GDT_Float32, 0, 0 );
|
||||
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Attempt to interpolate any pixels that are nodata. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
memset( pabyFiltMask, 0, nXSize );
|
||||
for( iX = 0; iX < nXSize; iX++ )
|
||||
{
|
||||
int iStep, iQuad;
|
||||
int nThisMaxSearchDist = nMaxSearchDist;
|
||||
|
||||
// If this was a valid target - no change.
|
||||
if( pabyMask[iX] )
|
||||
continue;
|
||||
|
||||
// Quadrants 0:topleft, 1:bottomleft, 2:topright, 3:bottomright
|
||||
double adfQuadDist[4];
|
||||
double adfQuadValue[4];
|
||||
|
||||
for( iQuad = 0; iQuad < 4; iQuad++ )
|
||||
{
|
||||
adfQuadDist[iQuad] = dfMaxSearchDist + 1.0;
|
||||
adfQuadValue[iQuad] = 0.0;
|
||||
}
|
||||
|
||||
// Step left and right by one pixel searching for the closest
|
||||
// target value for each quadrant.
|
||||
for( iStep = 0; iStep < nThisMaxSearchDist; iStep++ )
|
||||
{
|
||||
int iLeftX = MAX(0,iX - iStep);
|
||||
int iRightX = MIN(nXSize-1,iX + iStep);
|
||||
|
||||
// top left includes current line
|
||||
QUAD_CHECK(adfQuadDist[0],adfQuadValue[0],
|
||||
iLeftX, panTopDownY[iLeftX], iX, iY,
|
||||
pafTopDownValue[iLeftX] );
|
||||
|
||||
// bottom left
|
||||
QUAD_CHECK(adfQuadDist[1],adfQuadValue[1],
|
||||
iLeftX, panLastY[iLeftX], iX, iY,
|
||||
pafLastValue[iLeftX] );
|
||||
|
||||
// top right and bottom right do no include center pixel.
|
||||
if( iStep == 0 )
|
||||
continue;
|
||||
|
||||
// top right includes current line
|
||||
QUAD_CHECK(adfQuadDist[2],adfQuadValue[2],
|
||||
iRightX, panTopDownY[iRightX], iX, iY,
|
||||
pafTopDownValue[iRightX] );
|
||||
|
||||
// bottom right
|
||||
QUAD_CHECK(adfQuadDist[3],adfQuadValue[3],
|
||||
iRightX, panLastY[iRightX], iX, iY,
|
||||
pafLastValue[iRightX] );
|
||||
|
||||
// every four steps, recompute maximum distance.
|
||||
if( (iStep & 0x3) == 0 )
|
||||
nThisMaxSearchDist = (int) floor(
|
||||
MAX(MAX(adfQuadDist[0],adfQuadDist[1]),
|
||||
MAX(adfQuadDist[2],adfQuadDist[3])) );
|
||||
}
|
||||
|
||||
double dfWeightSum = 0.0;
|
||||
double dfValueSum = 0.0;
|
||||
|
||||
for( iQuad = 0; iQuad < 4; iQuad++ )
|
||||
{
|
||||
if( adfQuadDist[iQuad] <= dfMaxSearchDist )
|
||||
{
|
||||
double dfWeight = 1.0 / adfQuadDist[iQuad];
|
||||
|
||||
dfWeightSum += dfWeight;
|
||||
dfValueSum += adfQuadValue[iQuad] * dfWeight;
|
||||
}
|
||||
}
|
||||
|
||||
if( dfWeightSum > 0.0 )
|
||||
{
|
||||
pabyMask[iX] = 255;
|
||||
pabyFiltMask[iX] = 255;
|
||||
pafScanline[iX] = (float) (dfValueSum / dfWeightSum);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Write out the updated data and mask information. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
eErr =
|
||||
GDALRasterIO( hTargetBand, GF_Write, 0, iY, nXSize, 1,
|
||||
pafScanline, nXSize, 1, GDT_Float32, 0, 0 );
|
||||
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
eErr =
|
||||
GDALRasterIO( hFiltMaskBand, GF_Write, 0, iY, nXSize, 1,
|
||||
pabyFiltMask, nXSize, 1, GDT_Byte, 0, 0 );
|
||||
|
||||
if( eErr != CE_None )
|
||||
break;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Flip this/last buffers. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
{
|
||||
float *pafTmp = pafThisValue;
|
||||
pafThisValue = pafLastValue;
|
||||
pafLastValue = pafTmp;
|
||||
|
||||
GUInt32 *panTmp = panThisY;
|
||||
panThisY = panLastY;
|
||||
panLastY = panTmp;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* report progress. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( eErr == CE_None
|
||||
&& !pfnProgress( dfProgressRatio*(0.5+0.5*(nYSize-iY) / (double)nYSize),
|
||||
"Filling...", pProgressArg ) )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
|
||||
eErr = CE_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Now we will do iterative average filters over the */
|
||||
/* interpolated values to smooth things out and make linear */
|
||||
/* artifacts less obvious. */
|
||||
/* ==================================================================== */
|
||||
if( eErr == CE_None && nSmoothingIterations > 0 )
|
||||
{
|
||||
// force masks to be to flushed and recomputed.
|
||||
GDALFlushRasterCache( hMaskBand );
|
||||
|
||||
void *pScaledProgress;
|
||||
pScaledProgress =
|
||||
GDALCreateScaledProgress( dfProgressRatio, 1.0, pfnProgress, NULL );
|
||||
|
||||
eErr = GDALMultiFilter( hTargetBand, hMaskBand, hFiltMaskBand,
|
||||
nSmoothingIterations,
|
||||
GDALScaledProgress, pScaledProgress );
|
||||
|
||||
GDALDestroyScaledProgress( pScaledProgress );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Close and clean up temporary files. Free working buffers */
|
||||
/* -------------------------------------------------------------------- */
|
||||
end:
|
||||
CPLFree(panLastY);
|
||||
CPLFree(panThisY);
|
||||
CPLFree(panTopDownY);
|
||||
CPLFree(pafLastValue);
|
||||
CPLFree(pafThisValue);
|
||||
CPLFree(pafTopDownValue);
|
||||
CPLFree(pafScanline);
|
||||
CPLFree(pabyMask);
|
||||
CPLFree(pabyFiltMask);
|
||||
|
||||
GDALClose( hYDS );
|
||||
GDALClose( hValDS );
|
||||
GDALClose( hFiltMaskDS );
|
||||
|
||||
CSLDestroy(papszWorkFileOptions);
|
||||
|
||||
GDALDeleteDataset( hDriver, osYTmpFile );
|
||||
GDALDeleteDataset( hDriver, osValTmpFile );
|
||||
GDALDeleteDataset( hDriver, osFiltMaskTmpFile );
|
||||
|
||||
return eErr;
|
||||
}
|
||||
812
bazaar/plugin/gdal/alg/thinplatespline.cpp
Normal file
812
bazaar/plugin/gdal/alg/thinplatespline.cpp
Normal file
|
|
@ -0,0 +1,812 @@
|
|||
/******************************************************************************
|
||||
* $Id: thinplatespline.cpp 27546 2014-07-22 22:40:02Z rouault $
|
||||
*
|
||||
* Project: GDAL Warp API
|
||||
* Purpose: Implemenentation of 2D Thin Plate Spline transformer.
|
||||
* Author: VIZRT Development Team.
|
||||
*
|
||||
* This code was provided by Gilad Ronnen (gro at visrt dot com) with
|
||||
* permission to reuse under the following license.
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2004, VIZRT Inc.
|
||||
* Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_ARMADILLO
|
||||
/* Include before #define A(r,c) because armadillo uses A in its include files */
|
||||
#include "armadillo"
|
||||
#endif
|
||||
|
||||
#include "thinplatespline.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//// vizGeorefSpline2D
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define A(r,c) _AA[ _nof_eqs * (r) + (c) ]
|
||||
#define Ainv(r,c) _Ainv[ _nof_eqs * (r) + (c) ]
|
||||
|
||||
|
||||
#define VIZ_GEOREF_SPLINE_DEBUG 0
|
||||
|
||||
#ifndef HAVE_ARMADILLO
|
||||
static int matrixInvert( int N, double input[], double output[] );
|
||||
#endif
|
||||
|
||||
void VizGeorefSpline2D::grow_points()
|
||||
|
||||
{
|
||||
int new_max = _max_nof_points*2 + 2 + 3;
|
||||
int i;
|
||||
|
||||
x = (double *) VSIRealloc( x, sizeof(double) * new_max );
|
||||
y = (double *) VSIRealloc( y, sizeof(double) * new_max );
|
||||
u = (double *) VSIRealloc( u, sizeof(double) * new_max );
|
||||
unused = (int *) VSIRealloc( unused, sizeof(int) * new_max );
|
||||
index = (int *) VSIRealloc( index, sizeof(int) * new_max );
|
||||
for( i = 0; i < VIZGEOREF_MAX_VARS; i++ )
|
||||
{
|
||||
rhs[i] = (double *)
|
||||
VSIRealloc( rhs[i], sizeof(double) * new_max );
|
||||
coef[i] = (double *)
|
||||
VSIRealloc( coef[i], sizeof(double) * new_max );
|
||||
if( _max_nof_points == 0 )
|
||||
{
|
||||
memset(rhs[i], 0, 3 * sizeof(double));
|
||||
memset(coef[i], 0, 3 * sizeof(double));
|
||||
}
|
||||
}
|
||||
|
||||
_max_nof_points = new_max - 3;
|
||||
}
|
||||
|
||||
int VizGeorefSpline2D::add_point( const double Px, const double Py, const double *Pvars )
|
||||
{
|
||||
type = VIZ_GEOREF_SPLINE_POINT_WAS_ADDED;
|
||||
int i;
|
||||
|
||||
if( _nof_points == _max_nof_points )
|
||||
grow_points();
|
||||
|
||||
i = _nof_points;
|
||||
//A new point is added
|
||||
x[i] = Px;
|
||||
y[i] = Py;
|
||||
for ( int j = 0; j < _nof_vars; j++ )
|
||||
rhs[j][i+3] = Pvars[j];
|
||||
_nof_points++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool VizGeorefSpline2D::change_point(int index, double Px, double Py, double* Pvars)
|
||||
{
|
||||
if ( index < _nof_points )
|
||||
{
|
||||
int i = index;
|
||||
x[i] = Px;
|
||||
y[i] = Py;
|
||||
for ( int j = 0; j < _nof_vars; j++ )
|
||||
rhs[j][i+3] = Pvars[j];
|
||||
}
|
||||
|
||||
return( true );
|
||||
}
|
||||
|
||||
bool VizGeorefSpline2D::get_xy(int index, double& outX, double& outY)
|
||||
{
|
||||
bool ok;
|
||||
|
||||
if ( index < _nof_points )
|
||||
{
|
||||
ok = true;
|
||||
outX = x[index];
|
||||
outY = y[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = false;
|
||||
outX = outY = 0.0f;
|
||||
}
|
||||
|
||||
return(ok);
|
||||
}
|
||||
|
||||
int VizGeorefSpline2D::delete_point(const double Px, const double Py )
|
||||
{
|
||||
for ( int i = 0; i < _nof_points; i++ )
|
||||
{
|
||||
if ( ( fabs(Px - x[i]) <= _tx ) && ( fabs(Py - y[i]) <= _ty ) )
|
||||
{
|
||||
for ( int j = i; j < _nof_points - 1; j++ )
|
||||
{
|
||||
x[j] = x[j+1];
|
||||
y[j] = y[j+1];
|
||||
for ( int k = 0; k < _nof_vars; k++ )
|
||||
rhs[k][j+3] = rhs[k][j+3+1];
|
||||
}
|
||||
_nof_points--;
|
||||
type = VIZ_GEOREF_SPLINE_POINT_WAS_DELETED;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SQ(x) ((x)*(x))
|
||||
|
||||
static CPL_INLINE double VizGeorefSpline2DBase_func( const double x1, const double y1,
|
||||
const double x2, const double y2 )
|
||||
{
|
||||
double dist = SQ( x2 - x1 ) + SQ( y2 - y1 );
|
||||
return dist ? dist * log( dist ) : 0.0;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && defined(__x86_64__)
|
||||
|
||||
/* Derived and adapted from code originating from: */
|
||||
|
||||
/* @(#)e_log.c 1.3 95/01/18 */
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunSoft, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
/* __ieee754_log(x)
|
||||
* Return the logrithm of x
|
||||
*
|
||||
* Method :
|
||||
* 1. Argument Reduction: find k and f such that
|
||||
* x = 2^k * (1+f),
|
||||
* where sqrt(2)/2 < 1+f < sqrt(2) .
|
||||
*
|
||||
* 2. Approximation of log(1+f).
|
||||
* Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
|
||||
* = 2s + 2/3 s**3 + 2/5 s**5 + .....,
|
||||
* = 2s + s*R
|
||||
* We use a special Reme algorithm on [0,0.1716] to generate
|
||||
* a polynomial of degree 14 to approximate R The maximum error
|
||||
* of this polynomial approximation is bounded by 2**-58.45. In
|
||||
* other words,
|
||||
* 2 4 6 8 10 12 14
|
||||
* R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s
|
||||
* (the values of Lg1 to Lg7 are listed in the program)
|
||||
* and
|
||||
* | 2 14 | -58.45
|
||||
* | Lg1*s +...+Lg7*s - R(z) | <= 2
|
||||
* | |
|
||||
* Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
|
||||
* In order to guarantee error in log below 1ulp, we compute log
|
||||
* by
|
||||
* log(1+f) = f - s*(f - R) (if f is not too large)
|
||||
* log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
|
||||
*
|
||||
* 3. Finally, log(x) = k*ln2 + log(1+f).
|
||||
* = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
|
||||
* Here ln2 is split into two floating point number:
|
||||
* ln2_hi + ln2_lo,
|
||||
* where n*ln2_hi is always exact for |n| < 2000.
|
||||
*
|
||||
* Special cases:
|
||||
* log(x) is NaN with signal if x < 0 (including -INF) ;
|
||||
* log(+INF) is +INF; log(0) is -INF with signal;
|
||||
* log(NaN) is that NaN with no signal.
|
||||
*
|
||||
* Accuracy:
|
||||
* according to an error analysis, the error is always less than
|
||||
* 1 ulp (unit in the last place).
|
||||
*
|
||||
* Constants:
|
||||
* The hexadecimal values are the intended ones for the following
|
||||
* constants. The decimal values may be used, provided that the
|
||||
* compiler will convert from decimal to binary accurately enough
|
||||
* to produce the hexadecimal values shown.
|
||||
*/
|
||||
|
||||
typedef double V2DF __attribute__ ((__vector_size__ (16)));
|
||||
typedef union
|
||||
{
|
||||
V2DF v2;
|
||||
double d[2];
|
||||
} v2dfunion;
|
||||
|
||||
typedef union
|
||||
{
|
||||
int i[2];
|
||||
long long li;
|
||||
} i64union;
|
||||
|
||||
static const V2DF
|
||||
v2_ln2_div_2pow20 = {6.93147180559945286e-01 / 1048576, 6.93147180559945286e-01 / 1048576},
|
||||
v2_Lg1 = {6.666666666666735130e-01, 6.666666666666735130e-01},
|
||||
v2_Lg2 = {3.999999999940941908e-01, 3.999999999940941908e-01},
|
||||
v2_Lg3 = {2.857142874366239149e-01, 2.857142874366239149e-01},
|
||||
v2_Lg4 = {2.222219843214978396e-01, 2.222219843214978396e-01},
|
||||
v2_Lg5 = {1.818357216161805012e-01, 1.818357216161805012e-01},
|
||||
v2_Lg6 = {1.531383769920937332e-01, 1.531383769920937332e-01},
|
||||
/*v2_Lg7 = {1.479819860511658591e-01, 1.479819860511658591e-01}, */
|
||||
v2_one = { 1.0, 1.0 },
|
||||
v2_const1023_mul_2pow20 = { 1023.0 * 1048576, 1023.0 * 1048576};
|
||||
|
||||
#define GET_HIGH_WORD(hx,x) memcpy(&hx,((char*)&x+4),4)
|
||||
#define SET_HIGH_WORD(x,hx) memcpy(((char*)&x+4),&hx,4)
|
||||
|
||||
#define MAKE_WIDE_CST(x) ((((long long)(x)) << 32) | (x))
|
||||
static const long long cst_expmask = MAKE_WIDE_CST(0xfff00000);
|
||||
static const long long cst_0x95f64 = MAKE_WIDE_CST(0x00095f64);
|
||||
static const long long cst_0x100000 = MAKE_WIDE_CST(0x00100000);
|
||||
static const long long cst_0x3ff00000 = MAKE_WIDE_CST(0x3ff00000);
|
||||
|
||||
/* Modified version of __ieee754_log(), less precise than log() but a bit */
|
||||
/* faste, and computing 4 log() at a time. Assumes that the values are > 0 */
|
||||
static void FastApproxLog4Val(v2dfunion* x)
|
||||
{
|
||||
V2DF f[2],s[2],z[2],R[2],w[2],t1[2],t2[2];
|
||||
v2dfunion dk[2];
|
||||
i64union k[2], hx[2], i[2];
|
||||
|
||||
GET_HIGH_WORD(hx[0].i[0],x[0].d[0]);
|
||||
GET_HIGH_WORD(hx[0].i[1],x[0].d[1]);
|
||||
k[0].li = hx[0].li & cst_expmask;
|
||||
hx[0].li &= ~cst_expmask;
|
||||
i[0].li = (hx[0].li + cst_0x95f64) & cst_0x100000;
|
||||
hx[0].li |= i[0].li ^ cst_0x3ff00000;
|
||||
SET_HIGH_WORD(x[0].d[0],hx[0].i[0]); /* normalize x or x/2 */
|
||||
SET_HIGH_WORD(x[0].d[1],hx[0].i[1]); /* normalize x or x/2 */
|
||||
k[0].li += i[0].li;
|
||||
dk[0].d[0] = (double)k[0].i[0];
|
||||
dk[0].d[1] = (double)k[0].i[1];
|
||||
|
||||
GET_HIGH_WORD(hx[1].i[0],x[1].d[0]);
|
||||
GET_HIGH_WORD(hx[1].i[1],x[1].d[1]);
|
||||
k[1].li = hx[1].li & cst_expmask;
|
||||
hx[1].li &= ~cst_expmask;
|
||||
i[1].li = (hx[1].li + cst_0x95f64) & cst_0x100000;
|
||||
hx[1].li |= i[1].li ^ cst_0x3ff00000;
|
||||
SET_HIGH_WORD(x[1].d[0],hx[1].i[0]); /* normalize x or x/2 */
|
||||
SET_HIGH_WORD(x[1].d[1],hx[1].i[1]); /* normalize x or x/2 */
|
||||
k[1].li += i[1].li;
|
||||
dk[1].d[0] = (double)k[1].i[0];
|
||||
dk[1].d[1] = (double)k[1].i[1];
|
||||
|
||||
f[0] = x[0].v2-v2_one;
|
||||
s[0] = f[0]/(x[0].v2+v2_one);
|
||||
z[0] = s[0]*s[0];
|
||||
w[0] = z[0]*z[0];
|
||||
t1[0]= w[0]*(v2_Lg2+w[0]*(v2_Lg4+w[0]*v2_Lg6));
|
||||
t2[0]= z[0]*(v2_Lg1+w[0]*(v2_Lg3+w[0]*(v2_Lg5/*+w[0]*v2_Lg7*/)));
|
||||
R[0] = t2[0]+t1[0];
|
||||
x[0].v2 = ((dk[0].v2 - v2_const1023_mul_2pow20)*v2_ln2_div_2pow20-(s[0]*(f[0]-R[0])-f[0]));
|
||||
|
||||
f[1] = x[1].v2-v2_one;
|
||||
s[1] = f[1]/(x[1].v2+v2_one);
|
||||
z[1] = s[1]*s[1];
|
||||
w[1] = z[1]*z[1];
|
||||
t1[1]= w[1]*(v2_Lg2+w[1]*(v2_Lg4+w[1]*v2_Lg6));
|
||||
t2[1]= z[1]*(v2_Lg1+w[1]*(v2_Lg3+w[1]*(v2_Lg5/*+w[1]*v2_Lg7*/)));
|
||||
R[1] = t2[1]+t1[1];
|
||||
x[1].v2 = ((dk[1].v2- v2_const1023_mul_2pow20)*v2_ln2_div_2pow20-(s[1]*(f[1]-R[1])-f[1]));
|
||||
}
|
||||
|
||||
static CPL_INLINE void VizGeorefSpline2DBase_func4( double* res,
|
||||
const double* pxy,
|
||||
const double* xr, const double* yr )
|
||||
{
|
||||
v2dfunion x1v, y1v, xv[2], yv[2], dist[2], resv[2];
|
||||
xv[0].d[0] = xr[0];
|
||||
xv[0].d[1] = xr[1];
|
||||
xv[1].d[0] = xr[2];
|
||||
xv[1].d[1] = xr[3];
|
||||
yv[0].d[0] = yr[0];
|
||||
yv[0].d[1] = yr[1];
|
||||
yv[1].d[0] = yr[2];
|
||||
yv[1].d[1] = yr[3];
|
||||
x1v.d[0] = pxy[0];
|
||||
x1v.d[1] = pxy[0];
|
||||
y1v.d[0] = pxy[1];
|
||||
y1v.d[1] = pxy[1];
|
||||
dist[0].v2 = SQ( xv[0].v2 - x1v.v2 ) + SQ( yv[0].v2 - y1v.v2 );
|
||||
dist[1].v2 = SQ( xv[1].v2 - x1v.v2 ) + SQ( yv[1].v2 - y1v.v2 );
|
||||
resv[0] = dist[0];
|
||||
resv[1] = dist[1];
|
||||
FastApproxLog4Val(dist);
|
||||
resv[0].v2 *= dist[0].v2;
|
||||
resv[1].v2 *= dist[1].v2;
|
||||
res[0] = resv[0].d[0];
|
||||
res[1] = resv[0].d[1];
|
||||
res[2] = resv[1].d[0];
|
||||
res[3] = resv[1].d[1];
|
||||
}
|
||||
#else
|
||||
static void VizGeorefSpline2DBase_func4( double* res,
|
||||
const double* pxy,
|
||||
const double* xr, const double* yr )
|
||||
{
|
||||
double dist0 = SQ( xr[0] - pxy[0] ) + SQ( yr[0] - pxy[1] );
|
||||
res[0] = dist0 ? dist0 * log(dist0) : 0.0;
|
||||
double dist1 = SQ( xr[1] - pxy[0] ) + SQ( yr[1] - pxy[1] );
|
||||
res[1] = dist1 ? dist1 * log(dist1) : 0.0;
|
||||
double dist2 = SQ( xr[2] - pxy[0] ) + SQ( yr[2] - pxy[1] );
|
||||
res[2] = dist2 ? dist2 * log(dist2) : 0.0;
|
||||
double dist3 = SQ( xr[3] - pxy[0] ) + SQ( yr[3] - pxy[1] );
|
||||
res[3] = dist3 ? dist3 * log(dist3) : 0.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int VizGeorefSpline2D::solve(void)
|
||||
{
|
||||
int r, c;
|
||||
int p;
|
||||
|
||||
// No points at all
|
||||
if ( _nof_points < 1 )
|
||||
{
|
||||
type = VIZ_GEOREF_SPLINE_ZERO_POINTS;
|
||||
return(0);
|
||||
}
|
||||
|
||||
// Only one point
|
||||
if ( _nof_points == 1 )
|
||||
{
|
||||
type = VIZ_GEOREF_SPLINE_ONE_POINT;
|
||||
return(1);
|
||||
}
|
||||
// Just 2 points - it is necessarily 1D case
|
||||
if ( _nof_points == 2 )
|
||||
{
|
||||
_dx = x[1] - x[0];
|
||||
_dy = y[1] - y[0];
|
||||
double fact = 1.0 / ( _dx * _dx + _dy * _dy );
|
||||
_dx *= fact;
|
||||
_dy *= fact;
|
||||
|
||||
type = VIZ_GEOREF_SPLINE_TWO_POINTS;
|
||||
return(2);
|
||||
}
|
||||
|
||||
// More than 2 points - first we have to check if it is 1D or 2D case
|
||||
|
||||
double xmax = x[0], xmin = x[0], ymax = y[0], ymin = y[0];
|
||||
double delx, dely;
|
||||
double xx, yy;
|
||||
double sumx = 0.0f, sumy= 0.0f, sumx2 = 0.0f, sumy2 = 0.0f, sumxy = 0.0f;
|
||||
double SSxx, SSyy, SSxy;
|
||||
|
||||
for ( p = 0; p < _nof_points; p++ )
|
||||
{
|
||||
xx = x[p];
|
||||
yy = y[p];
|
||||
|
||||
xmax = MAX( xmax, xx );
|
||||
xmin = MIN( xmin, xx );
|
||||
ymax = MAX( ymax, yy );
|
||||
ymin = MIN( ymin, yy );
|
||||
|
||||
sumx += xx;
|
||||
sumx2 += xx * xx;
|
||||
sumy += yy;
|
||||
sumy2 += yy * yy;
|
||||
sumxy += xx * yy;
|
||||
}
|
||||
delx = xmax - xmin;
|
||||
dely = ymax - ymin;
|
||||
|
||||
SSxx = sumx2 - sumx * sumx / _nof_points;
|
||||
SSyy = sumy2 - sumy * sumy / _nof_points;
|
||||
SSxy = sumxy - sumx * sumy / _nof_points;
|
||||
|
||||
if ( delx < 0.001 * dely || dely < 0.001 * delx ||
|
||||
fabs ( SSxy * SSxy / ( SSxx * SSyy ) ) > 0.99 )
|
||||
{
|
||||
int p1;
|
||||
|
||||
type = VIZ_GEOREF_SPLINE_ONE_DIMENSIONAL;
|
||||
|
||||
_dx = _nof_points * sumx2 - sumx * sumx;
|
||||
_dy = _nof_points * sumy2 - sumy * sumy;
|
||||
double fact = 1.0 / sqrt( _dx * _dx + _dy * _dy );
|
||||
_dx *= fact;
|
||||
_dy *= fact;
|
||||
|
||||
for ( p = 0; p < _nof_points; p++ )
|
||||
{
|
||||
double dxp = x[p] - x[0];
|
||||
double dyp = y[p] - y[0];
|
||||
u[p] = _dx * dxp + _dy * dyp;
|
||||
unused[p] = 1;
|
||||
}
|
||||
|
||||
for ( p = 0; p < _nof_points; p++ )
|
||||
{
|
||||
int min_index = -1;
|
||||
double min_u = 0;
|
||||
for ( p1 = 0; p1 < _nof_points; p1++ )
|
||||
{
|
||||
if ( unused[p1] )
|
||||
{
|
||||
if ( min_index < 0 || u[p1] < min_u )
|
||||
{
|
||||
min_index = p1;
|
||||
min_u = u[p1];
|
||||
}
|
||||
}
|
||||
}
|
||||
index[p] = min_index;
|
||||
unused[min_index] = 0;
|
||||
}
|
||||
|
||||
return(3);
|
||||
}
|
||||
|
||||
type = VIZ_GEOREF_SPLINE_FULL;
|
||||
// Make the necessary memory allocations
|
||||
|
||||
_nof_eqs = _nof_points + 3;
|
||||
|
||||
if( _nof_eqs > INT_MAX / _nof_eqs )
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined, "Too many coefficients. Computation aborted.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
double* _AA = ( double * )VSICalloc( _nof_eqs * _nof_eqs, sizeof( double ) );
|
||||
double* _Ainv = ( double * )VSICalloc( _nof_eqs * _nof_eqs, sizeof( double ) );
|
||||
|
||||
if( _AA == NULL || _Ainv == NULL )
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined, "Out-of-memory while allocating temporary arrays. Computation aborted.");
|
||||
VSIFree(_AA);
|
||||
VSIFree(_Ainv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Calc the values of the matrix A
|
||||
for ( r = 0; r < 3; r++ )
|
||||
for ( c = 0; c < 3; c++ )
|
||||
A(r,c) = 0.0;
|
||||
|
||||
for ( c = 0; c < _nof_points; c++ )
|
||||
{
|
||||
A(0,c+3) = 1.0;
|
||||
A(1,c+3) = x[c];
|
||||
A(2,c+3) = y[c];
|
||||
|
||||
A(c+3,0) = 1.0;
|
||||
A(c+3,1) = x[c];
|
||||
A(c+3,2) = y[c];
|
||||
}
|
||||
|
||||
for ( r = 0; r < _nof_points; r++ )
|
||||
for ( c = r; c < _nof_points; c++ )
|
||||
{
|
||||
A(r+3,c+3) = VizGeorefSpline2DBase_func( x[r], y[r], x[c], y[c] );
|
||||
if ( r != c )
|
||||
A(c+3,r+3 ) = A(r+3,c+3);
|
||||
}
|
||||
|
||||
#if VIZ_GEOREF_SPLINE_DEBUG
|
||||
|
||||
for ( r = 0; r < _nof_eqs; r++ )
|
||||
{
|
||||
for ( c = 0; c < _nof_eqs; c++ )
|
||||
fprintf(stderr, "%f", A(r,c));
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int ret = 4;
|
||||
#ifdef HAVE_ARMADILLO
|
||||
try
|
||||
{
|
||||
arma::mat matA(_AA,_nof_eqs,_nof_eqs,false);
|
||||
arma::mat matRHS(_nof_eqs, _nof_vars);
|
||||
int row, col;
|
||||
for(row = 0; row < _nof_eqs; row++)
|
||||
for(col = 0; col < _nof_vars; col++)
|
||||
matRHS.at(row, col) = rhs[col][row];
|
||||
arma::mat matCoefs(_nof_vars, _nof_eqs);
|
||||
if( !arma::solve(matCoefs, matA, matRHS) )
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined, "There is a problem to invert the interpolation matrix.");
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(row = 0; row < _nof_eqs; row++)
|
||||
for(col = 0; col < _nof_vars; col++)
|
||||
coef[col][row] = matCoefs.at(row, col);
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined, "There is a problem to invert the interpolation matrix.");
|
||||
ret = 0;
|
||||
}
|
||||
#else
|
||||
// Invert the matrix
|
||||
int status = matrixInvert( _nof_eqs, _AA, _Ainv );
|
||||
|
||||
if ( !status )
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_AppDefined, "There is a problem to invert the interpolation matrix.");
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// calc the coefs
|
||||
for ( int v = 0; v < _nof_vars; v++ )
|
||||
for ( r = 0; r < _nof_eqs; r++ )
|
||||
{
|
||||
coef[v][r] = 0.0;
|
||||
for ( c = 0; c < _nof_eqs; c++ )
|
||||
coef[v][r] += Ainv(r,c) * rhs[v][c];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
VSIFree(_AA);
|
||||
VSIFree(_Ainv);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int VizGeorefSpline2D::get_point( const double Px, const double Py, double *vars )
|
||||
{
|
||||
int v, r;
|
||||
double tmp, Pu;
|
||||
double fact;
|
||||
int leftP=0, rightP=0, found = 0;
|
||||
|
||||
switch ( type )
|
||||
{
|
||||
case VIZ_GEOREF_SPLINE_ZERO_POINTS :
|
||||
for ( v = 0; v < _nof_vars; v++ )
|
||||
vars[v] = 0.0;
|
||||
break;
|
||||
case VIZ_GEOREF_SPLINE_ONE_POINT :
|
||||
for ( v = 0; v < _nof_vars; v++ )
|
||||
vars[v] = rhs[v][3];
|
||||
break;
|
||||
case VIZ_GEOREF_SPLINE_TWO_POINTS :
|
||||
fact = _dx * ( Px - x[0] ) + _dy * ( Py - y[0] );
|
||||
for ( v = 0; v < _nof_vars; v++ )
|
||||
vars[v] = ( 1 - fact ) * rhs[v][3] + fact * rhs[v][4];
|
||||
break;
|
||||
case VIZ_GEOREF_SPLINE_ONE_DIMENSIONAL :
|
||||
Pu = _dx * ( Px - x[0] ) + _dy * ( Py - y[0] );
|
||||
if ( Pu <= u[index[0]] )
|
||||
{
|
||||
leftP = index[0];
|
||||
rightP = index[1];
|
||||
}
|
||||
else if ( Pu >= u[index[_nof_points-1]] )
|
||||
{
|
||||
leftP = index[_nof_points-2];
|
||||
rightP = index[_nof_points-1];
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( r = 1; !found && r < _nof_points; r++ )
|
||||
{
|
||||
leftP = index[r-1];
|
||||
rightP = index[r];
|
||||
if ( Pu >= u[leftP] && Pu <= u[rightP] )
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
fact = ( Pu - u[leftP] ) / ( u[rightP] - u[leftP] );
|
||||
for ( v = 0; v < _nof_vars; v++ )
|
||||
vars[v] = ( 1.0 - fact ) * rhs[v][leftP+3] +
|
||||
fact * rhs[v][rightP+3];
|
||||
break;
|
||||
case VIZ_GEOREF_SPLINE_FULL :
|
||||
{
|
||||
double Pxy[2] = { Px, Py };
|
||||
for ( v = 0; v < _nof_vars; v++ )
|
||||
vars[v] = coef[v][0] + coef[v][1] * Px + coef[v][2] * Py;
|
||||
|
||||
for ( r = 0; r < (_nof_points & (~3)); r+=4 )
|
||||
{
|
||||
double tmp[4];
|
||||
VizGeorefSpline2DBase_func4( tmp, Pxy, &x[r], &y[r] );
|
||||
for ( v= 0; v < _nof_vars; v++ )
|
||||
vars[v] += coef[v][r+3] * tmp[0] +
|
||||
coef[v][r+3+1] * tmp[1] +
|
||||
coef[v][r+3+2] * tmp[2] +
|
||||
coef[v][r+3+3] * tmp[3];
|
||||
}
|
||||
for ( ; r < _nof_points; r++ )
|
||||
{
|
||||
tmp = VizGeorefSpline2DBase_func( Px, Py, x[r], y[r] );
|
||||
for ( v= 0; v < _nof_vars; v++ )
|
||||
vars[v] += coef[v][r+3] * tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VIZ_GEOREF_SPLINE_POINT_WAS_ADDED :
|
||||
fprintf(stderr, " A point was added after the last solve\n");
|
||||
fprintf(stderr, " NO interpolation - return values are zero\n");
|
||||
for ( v = 0; v < _nof_vars; v++ )
|
||||
vars[v] = 0.0;
|
||||
return(0);
|
||||
break;
|
||||
case VIZ_GEOREF_SPLINE_POINT_WAS_DELETED :
|
||||
fprintf(stderr, " A point was deleted after the last solve\n");
|
||||
fprintf(stderr, " NO interpolation - return values are zero\n");
|
||||
for ( v = 0; v < _nof_vars; v++ )
|
||||
vars[v] = 0.0;
|
||||
return(0);
|
||||
break;
|
||||
default :
|
||||
return(0);
|
||||
break;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
#ifndef HAVE_ARMADILLO
|
||||
static int matrixInvert( int N, double input[], double output[] )
|
||||
{
|
||||
// Receives an array of dimension NxN as input. This is passed as a one-
|
||||
// dimensional array of N-squared size. It produces the inverse of the
|
||||
// input matrix, returned as output, also of size N-squared. The Gauss-
|
||||
// Jordan Elimination method is used. (Adapted from a BASIC routine in
|
||||
// "Basic Scientific Subroutines Vol. 1", courtesy of Scott Edwards.)
|
||||
|
||||
// Array elements 0...N-1 are for the first row, N...2N-1 are for the
|
||||
// second row, etc.
|
||||
|
||||
// We need to have a temporary array of size N x 2N. We'll refer to the
|
||||
// "left" and "right" halves of this array.
|
||||
|
||||
int row, col;
|
||||
|
||||
#if 0
|
||||
fprintf(stderr, "Matrix Inversion input matrix (N=%d)\n", N);
|
||||
for ( row=0; row<N; row++ )
|
||||
{
|
||||
for ( col=0; col<N; col++ )
|
||||
{
|
||||
fprintf(stderr, "%5.2f ", input[row*N + col ] );
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
int tempSize = 2 * N * N;
|
||||
double* temp = (double*) new double[ tempSize ];
|
||||
double ftemp;
|
||||
|
||||
if (temp == 0) {
|
||||
|
||||
CPLError(CE_Failure, CPLE_AppDefined, "matrixInvert(): ERROR - memory allocation failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// First create a double-width matrix with the input array on the left
|
||||
// and the identity matrix on the right.
|
||||
|
||||
for ( row=0; row<N; row++ )
|
||||
{
|
||||
for ( col=0; col<N; col++ )
|
||||
{
|
||||
// Our index into the temp array is X2 because it's twice as wide
|
||||
// as the input matrix.
|
||||
|
||||
temp[ 2*row*N + col ] = input[ row*N+col ]; // left = input matrix
|
||||
temp[ 2*row*N + col + N ] = 0.0f; // right = 0
|
||||
}
|
||||
temp[ 2*row*N + row + N ] = 1.0f; // 1 on the diagonal of RHS
|
||||
}
|
||||
|
||||
// Now perform row-oriented operations to convert the left hand side
|
||||
// of temp to the identity matrix. The inverse of input will then be
|
||||
// on the right.
|
||||
|
||||
int max;
|
||||
int k=0;
|
||||
for (k = 0; k < N; k++)
|
||||
{
|
||||
if (k+1 < N) // if not on the last row
|
||||
{
|
||||
max = k;
|
||||
for (row = k+1; row < N; row++) // find the maximum element
|
||||
{
|
||||
if (fabs( temp[row*2*N + k] ) > fabs( temp[max*2*N + k] ))
|
||||
{
|
||||
max = row;
|
||||
}
|
||||
}
|
||||
|
||||
if (max != k) // swap all the elements in the two rows
|
||||
{
|
||||
for (col=k; col<2*N; col++)
|
||||
{
|
||||
ftemp = temp[k*2*N + col];
|
||||
temp[k*2*N + col] = temp[max*2*N + col];
|
||||
temp[max*2*N + col] = ftemp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ftemp = temp[ k*2*N + k ];
|
||||
if ( ftemp == 0.0f ) // matrix cannot be inverted
|
||||
{
|
||||
delete[] temp;
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( col=k; col<2*N; col++ )
|
||||
{
|
||||
temp[ k*2*N + col ] /= ftemp;
|
||||
}
|
||||
|
||||
int i2 = k*2*N ;
|
||||
for ( row=0; row<N; row++ )
|
||||
{
|
||||
if ( row != k )
|
||||
{
|
||||
int i1 = row*2*N;
|
||||
ftemp = temp[ i1 + k ];
|
||||
for ( col=k; col<2*N; col++ )
|
||||
{
|
||||
temp[ i1 + col ] -= ftemp * temp[ i2 + col ];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve inverse from the right side of temp
|
||||
|
||||
for (row = 0; row < N; row++)
|
||||
{
|
||||
for (col = 0; col < N; col++)
|
||||
{
|
||||
output[row*N + col] = temp[row*2*N + col + N ];
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
fprintf(stderr, "Matrix Inversion result matrix:\n");
|
||||
for ( row=0; row<N; row++ )
|
||||
{
|
||||
for ( col=0; col<N; col++ )
|
||||
{
|
||||
fprintf(stderr, "%5.2f ", output[row*N + col ] );
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
delete [] temp; // free memory
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
170
bazaar/plugin/gdal/alg/thinplatespline.h
Normal file
170
bazaar/plugin/gdal/alg/thinplatespline.h
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/******************************************************************************
|
||||
* $Id: thinplatespline.h 26650 2013-11-24 14:05:58Z rouault $
|
||||
*
|
||||
* Project: GDAL Warp API
|
||||
* Purpose: Declarations for 2D Thin Plate Spline transformer.
|
||||
* Author: VIZRT Development Team.
|
||||
*
|
||||
* This code was provided by Gilad Ronnen (gro at visrt dot com) with
|
||||
* permission to reuse under the following license.
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2004, VIZRT Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_alg.h"
|
||||
#include "cpl_conv.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VIZ_GEOREF_SPLINE_ZERO_POINTS,
|
||||
VIZ_GEOREF_SPLINE_ONE_POINT,
|
||||
VIZ_GEOREF_SPLINE_TWO_POINTS,
|
||||
VIZ_GEOREF_SPLINE_ONE_DIMENSIONAL,
|
||||
VIZ_GEOREF_SPLINE_FULL,
|
||||
|
||||
VIZ_GEOREF_SPLINE_POINT_WAS_ADDED,
|
||||
VIZ_GEOREF_SPLINE_POINT_WAS_DELETED
|
||||
|
||||
} vizGeorefInterType;
|
||||
|
||||
//#define VIZ_GEOREF_SPLINE_MAX_POINTS 40
|
||||
#define VIZGEOREF_MAX_VARS 2
|
||||
|
||||
class VizGeorefSpline2D
|
||||
{
|
||||
public:
|
||||
|
||||
VizGeorefSpline2D(int nof_vars = 1){
|
||||
x = y = u = NULL;
|
||||
unused = index = NULL;
|
||||
for( int i = 0; i < nof_vars; i++ )
|
||||
{
|
||||
rhs[i] = NULL;
|
||||
coef[i] = NULL;
|
||||
}
|
||||
|
||||
_tx = _ty = 0.0;
|
||||
_ta = 10.0;
|
||||
_nof_points = 0;
|
||||
_nof_vars = nof_vars;
|
||||
_max_nof_points = 0;
|
||||
grow_points();
|
||||
type = VIZ_GEOREF_SPLINE_ZERO_POINTS;
|
||||
}
|
||||
|
||||
~VizGeorefSpline2D(){
|
||||
CPLFree( x );
|
||||
CPLFree( y );
|
||||
CPLFree( u );
|
||||
CPLFree( unused );
|
||||
CPLFree( index );
|
||||
for( int i = 0; i < _nof_vars; i++ )
|
||||
{
|
||||
CPLFree( rhs[i] );
|
||||
CPLFree( coef[i] );
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
int get_nof_points(){
|
||||
return _nof_points;
|
||||
}
|
||||
|
||||
void set_toler( double tx, double ty ){
|
||||
_tx = tx;
|
||||
_ty = ty;
|
||||
}
|
||||
|
||||
void get_toler( double& tx, double& ty) {
|
||||
tx = _tx;
|
||||
ty = _ty;
|
||||
}
|
||||
|
||||
vizGeorefInterType get_interpolation_type ( ){
|
||||
return type;
|
||||
}
|
||||
|
||||
void dump_data_points()
|
||||
{
|
||||
for ( int i = 0; i < _nof_points; i++ )
|
||||
{
|
||||
fprintf(stderr, "X = %f Y = %f Vars = ", x[i], y[i]);
|
||||
for ( int v = 0; v < _nof_vars; v++ )
|
||||
fprintf(stderr, "%f ", rhs[v][i+3]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
int delete_list()
|
||||
{
|
||||
_nof_points = 0;
|
||||
type = VIZ_GEOREF_SPLINE_ZERO_POINTS;
|
||||
if ( _AA )
|
||||
{
|
||||
CPLFree(_AA);
|
||||
_AA = NULL;
|
||||
}
|
||||
if ( _Ainv )
|
||||
{
|
||||
CPLFree(_Ainv);
|
||||
_Ainv = NULL;
|
||||
}
|
||||
return _nof_points;
|
||||
}
|
||||
#endif
|
||||
|
||||
void grow_points();
|
||||
int add_point( const double Px, const double Py, const double *Pvars );
|
||||
int get_point( const double Px, const double Py, double *Pvars );
|
||||
#if 0
|
||||
int delete_point(const double Px, const double Py );
|
||||
bool get_xy(int index, double& x, double& y);
|
||||
bool change_point(int index, double x, double y, double* Pvars);
|
||||
void reset(void) { _nof_points = 0; }
|
||||
#endif
|
||||
int solve(void);
|
||||
|
||||
private:
|
||||
|
||||
vizGeorefInterType type;
|
||||
|
||||
int _nof_vars;
|
||||
int _nof_points;
|
||||
int _max_nof_points;
|
||||
int _nof_eqs;
|
||||
|
||||
double _tx, _ty;
|
||||
double _ta;
|
||||
double _dx, _dy;
|
||||
|
||||
double *x; // [VIZ_GEOREF_SPLINE_MAX_POINTS+3];
|
||||
double *y; // [VIZ_GEOREF_SPLINE_MAX_POINTS+3];
|
||||
|
||||
// double rhs[VIZ_GEOREF_SPLINE_MAX_POINTS+3][VIZGEOREF_MAX_VARS];
|
||||
// double coef[VIZ_GEOREF_SPLINE_MAX_POINTS+3][VIZGEOREF_MAX_VARS];
|
||||
double *rhs[VIZGEOREF_MAX_VARS];
|
||||
double *coef[VIZGEOREF_MAX_VARS];
|
||||
|
||||
double *u; // [VIZ_GEOREF_SPLINE_MAX_POINTS];
|
||||
int *unused; // [VIZ_GEOREF_SPLINE_MAX_POINTS];
|
||||
int *index; // [VIZ_GEOREF_SPLINE_MAX_POINTS];
|
||||
};
|
||||
149
bazaar/plugin/gdal/cpl_config.h
Normal file
149
bazaar/plugin/gdal/cpl_config.h
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
#define CPL_DISABLE_DLL
|
||||
#define DISABLE_CPLID // ALLOW BLITZ
|
||||
|
||||
#define GDAL_COMPILATION
|
||||
|
||||
|
||||
|
||||
#ifndef _gdal_cpl_config_h_
|
||||
#define _gdal_cpl_config_h_
|
||||
|
||||
#define RENAME_INTERNAL_LIBTIFF_SYMBOLS
|
||||
#define RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS
|
||||
|
||||
// added to embed in U++ to fix plugin/tif interoperability
|
||||
#define TIFFSwabArrayOfDouble gdal_TIFFSwabArrayOfDouble
|
||||
#define TIFFSwabArrayOfLong gdal_TIFFSwabArrayOfLong
|
||||
#define TIFFSwabArrayOfShort gdal_TIFFSwabArrayOfShort
|
||||
#define TIFFSwabArrayOfTriples gdal_TIFFSwabArrayOfTriples
|
||||
#define TIFFSwabDouble gdal_TIFFSwabDouble
|
||||
#define TIFFSwabLong gdal_TIFFSwabLong
|
||||
#define TIFFSwabShort gdal_TIFFSwabShort
|
||||
#define _TIFFSwab16BitData gdal__TIFFSwab16BitData
|
||||
#define _TIFFSwab24BitData gdal__TIFFSwab24BitData
|
||||
#define _TIFFSwab32BitData gdal__TIFFSwab32BitData
|
||||
#define _TIFFSwab64BitData gdal__TIFFSwab64BitData
|
||||
|
||||
/* We define this here in general so that a VC++ build will publically
|
||||
declare STDCALL interfaces even if an application is built against it
|
||||
using MinGW */
|
||||
|
||||
#ifndef CPL_DISABLE_STDCALL
|
||||
# define CPL_STDCALL __stdcall
|
||||
#endif
|
||||
|
||||
#define HAVE_LIBZ 1
|
||||
|
||||
/* Define if you don't have vprintf but do have _doprnt. */
|
||||
#undef HAVE_DOPRNT
|
||||
|
||||
/* Define if you have the vprintf function. */
|
||||
#define HAVE_VPRINTF 1
|
||||
#define HAVE_VSNPRINTF 1
|
||||
#define HAVE_SNPRINTF 1
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1500)
|
||||
# define vsnprintf _vsnprintf
|
||||
#endif
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#define HAVE_GETCWD 1
|
||||
/* gmt_notunix.h from GMT project also redefines getcwd. See #3138 */
|
||||
#ifndef getcwd
|
||||
#define getcwd _getcwd
|
||||
#endif
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
#ifndef STDC_HEADERS
|
||||
# define STDC_HEADERS 1
|
||||
#endif
|
||||
|
||||
/* Define to 1 if you have the <assert.h> header file. */
|
||||
#define HAVE_ASSERT_H 1
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define HAVE_FCNTL_H 1
|
||||
|
||||
/* Define if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
#undef HAVE_LIBDL
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#define HAVE_LOCALE_H 1
|
||||
|
||||
#define HAVE_FLOAT_H 1
|
||||
|
||||
#define HAVE_ERRNO_H 1
|
||||
|
||||
#define HAVE_SEARCH_H 1
|
||||
|
||||
/* Define to 1 if you have the <direct.h> header file. */
|
||||
#define HAVE_DIRECT_H
|
||||
|
||||
/* Define to 1 if you have the `localtime_r' function. */
|
||||
#undef HAVE_LOCALTIME_R
|
||||
|
||||
#undef HAVE_DLFCN_H
|
||||
#undef HAVE_DBMALLOC_H
|
||||
#undef HAVE_LIBDBMALLOC
|
||||
#undef WORDS_BIGENDIAN
|
||||
|
||||
/* The size of a `int', as computed by sizeof. */
|
||||
#define SIZEOF_INT 4
|
||||
|
||||
/* The size of a `long', as computed by sizeof. */
|
||||
#define SIZEOF_LONG 4
|
||||
|
||||
/* The size of a `unsigned long', as computed by sizeof. */
|
||||
#define SIZEOF_UNSIGNED_LONG 4
|
||||
|
||||
/* The size of `void*', as computed by sizeof. */
|
||||
#ifdef _WIN64
|
||||
# define SIZEOF_VOIDP 8
|
||||
#else
|
||||
# define SIZEOF_VOIDP 4
|
||||
#endif
|
||||
|
||||
/* Set the native cpu bit order */
|
||||
#define HOST_FILLORDER FILLORDER_LSB2MSB
|
||||
|
||||
/* Define as 0 or 1 according to the floating point format suported by the
|
||||
machine */
|
||||
#define HAVE_IEEEFP 1
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
# ifndef inline
|
||||
# define inline __inline
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define lfind _lfind
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1310)
|
||||
# define VSI_STAT64 _stat
|
||||
# define VSI_STAT64_T _stat
|
||||
#else
|
||||
# define VSI_STAT64 _stat64
|
||||
# define VSI_STAT64_T __stat64
|
||||
#endif
|
||||
|
||||
/* VC6 doesn't known intptr_t */
|
||||
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
|
||||
typedef int intptr_t;
|
||||
#endif
|
||||
|
||||
#pragma warning(disable: 4786)
|
||||
|
||||
/* #define CPL_DISABLE_DLL */
|
||||
|
||||
#endif
|
||||
27
bazaar/plugin/gdal/frmts/GNUmakefile
Normal file
27
bazaar/plugin/gdal/frmts/GNUmakefile
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
|
||||
include ../GDALmake.opt
|
||||
|
||||
OBJ = o/gdalallregister.o
|
||||
|
||||
FRMT_FLAGS = $(foreach FRMT, $(GDAL_FORMATS), -DFRMT_$(FRMT))
|
||||
|
||||
%-install-obj:
|
||||
$(MAKE) -C $* install-obj
|
||||
|
||||
default: $(OBJ:.o=.$(OBJ_EXT)) $(foreach d,$(GDAL_FORMATS),$(d)-install-obj)
|
||||
|
||||
clean: $(foreach d,$(GDAL_FORMATS),$(d)-clean)
|
||||
rm -f *.o o/*.o o/*.a
|
||||
$(RM) o/*.lo
|
||||
|
||||
o/gdalallregister.$(OBJ_EXT): gdalallregister.cpp ../GDALmake.opt
|
||||
$(CXX) -c $(GDAL_INCLUDE) $(CXXFLAGS) $(FRMT_FLAGS) \
|
||||
-DGDAL_FORMATS="$(GDAL_FORMATS)" \
|
||||
gdalallregister.cpp -o o/gdalallregister.$(OBJ_EXT)
|
||||
|
||||
# We might want to add dynamically generated drivers here eventually.
|
||||
install:
|
||||
$(MAKE) -C vrt install
|
||||
$(MAKE) -C mem install
|
||||
$(MAKE) -C raw install
|
||||
15
bazaar/plugin/gdal/frmts/aaigrid/GNUmakefile
Normal file
15
bazaar/plugin/gdal/frmts/aaigrid/GNUmakefile
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
include ../../GDALmake.opt
|
||||
|
||||
OBJ = aaigriddataset.o
|
||||
|
||||
CPPFLAGS := $(CPPFLAGS) $(XTRA_OPT)
|
||||
|
||||
default: $(OBJ:.o=.$(OBJ_EXT))
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
|
||||
all: $(OBJ:.o=.$(OBJ_EXT))
|
||||
|
||||
install-obj: $(O_OBJ:.o=.$(OBJ_EXT))
|
||||
1353
bazaar/plugin/gdal/frmts/aaigrid/aaigriddataset.cpp
Normal file
1353
bazaar/plugin/gdal/frmts/aaigrid/aaigriddataset.cpp
Normal file
File diff suppressed because it is too large
Load diff
13
bazaar/plugin/gdal/frmts/aaigrid/makefile.vc
Normal file
13
bazaar/plugin/gdal/frmts/aaigrid/makefile.vc
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
OBJ = aaigriddataset.obj
|
||||
|
||||
GDAL_ROOT = ..\..
|
||||
|
||||
!INCLUDE $(GDAL_ROOT)\nmake.opt
|
||||
|
||||
default: $(OBJ)
|
||||
xcopy /D /Y *.obj ..\o
|
||||
|
||||
clean:
|
||||
-del *.obj
|
||||
|
||||
14
bazaar/plugin/gdal/frmts/adrg/GNUmakefile
Normal file
14
bazaar/plugin/gdal/frmts/adrg/GNUmakefile
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
|
||||
include ../../GDALmake.opt
|
||||
|
||||
OBJ = adrgdataset.o srpdataset.o
|
||||
|
||||
CPPFLAGS := $(CPPFLAGS) -I../iso8211
|
||||
|
||||
default: $(OBJ:.o=.$(OBJ_EXT))
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
|
||||
install-obj: $(O_OBJ:.o=.$(OBJ_EXT))
|
||||
2269
bazaar/plugin/gdal/frmts/adrg/adrgdataset.cpp
Normal file
2269
bazaar/plugin/gdal/frmts/adrg/adrgdataset.cpp
Normal file
File diff suppressed because it is too large
Load diff
16
bazaar/plugin/gdal/frmts/adrg/makefile.vc
Normal file
16
bazaar/plugin/gdal/frmts/adrg/makefile.vc
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
OBJ = adrgdataset.obj srpdataset.obj
|
||||
|
||||
EXTRAFLAGS = -I..\iso8211
|
||||
|
||||
GDAL_ROOT = ..\..
|
||||
|
||||
!INCLUDE $(GDAL_ROOT)\nmake.opt
|
||||
|
||||
default: $(OBJ)
|
||||
xcopy /D /Y *.obj ..\o
|
||||
|
||||
clean:
|
||||
-del *.obj
|
||||
|
||||
|
||||
1630
bazaar/plugin/gdal/frmts/adrg/srpdataset.cpp
Normal file
1630
bazaar/plugin/gdal/frmts/adrg/srpdataset.cpp
Normal file
File diff suppressed because it is too large
Load diff
31
bazaar/plugin/gdal/frmts/aigrid/GNUmakefile
Normal file
31
bazaar/plugin/gdal/frmts/aigrid/GNUmakefile
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
include ../../GDALmake.opt
|
||||
|
||||
AIGOBJ = gridlib.o aigopen.o aigccitt.o
|
||||
OBJ = aigdataset.o $(AIGOBJ)
|
||||
|
||||
CPPFLAGS := $(CPPFLAGS) -I../../ogr/ogrsf_frmts/avc
|
||||
|
||||
default: $(OBJ:.o=.$(OBJ_EXT))
|
||||
|
||||
clean:
|
||||
rm -f *.o aitest$(EXE) $(OBJ) $(O_OBJ)
|
||||
|
||||
aitest$(EXE): aitest.$(OBJ_EXT)
|
||||
$(LD) $(LDFLAGS) aitest.$(OBJ_EXT) $(CONFIG_LIBS) -o aitest$(EXE)
|
||||
|
||||
aigrid2tif$(EXE): aigrid2tif.$(OBJ_EXT)
|
||||
$(LD) $(LDFLAGS) aigrid2tif.$(OBJ_EXT) $(CONFIG_LIBS) -o aigrid2tif$(EXE)
|
||||
|
||||
$(OBJ) $(O_OBJ): aigrid.h
|
||||
|
||||
install-obj: $(O_OBJ:.o=.$(OBJ_EXT))
|
||||
|
||||
aitest-dist:
|
||||
rm -rf aitest_dist
|
||||
mkdir aitest_dist
|
||||
cp gridlib.c aitest.c aigrid.h aigopen.c aigccitt.c aitest_dist
|
||||
cp ../../port/cpl_{vsisimple,conv,error}.cpp aitest_dist
|
||||
cp ../../port/cpl_{port,conv,vsi,config,error}.h aitest_dist
|
||||
cp Makefile.dist aitest_dist/Makefile
|
||||
|
||||
19
bazaar/plugin/gdal/frmts/aigrid/Makefile.dist
Normal file
19
bazaar/plugin/gdal/frmts/aigrid/Makefile.dist
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
|
||||
OBJ = aigopen.o gridlib.o aigccitt.o \
|
||||
cpl_vsisimple.o cpl_conv.o cpl_error.o
|
||||
|
||||
default: aitest
|
||||
|
||||
aitest: $(OBJ)
|
||||
$(CXX) aitest.c $(OBJ) -o aitest
|
||||
|
||||
cpl_vsisimple.o: cpl_vsisimple.cpp
|
||||
$(CXX) -c cpl_vsisimple.cpp
|
||||
|
||||
cpl_conv.o: cpl_conv.cpp
|
||||
$(CXX) -c cpl_conv.cpp
|
||||
|
||||
cpl_error.o: cpl_error.cpp
|
||||
$(CXX) -c cpl_error.cpp
|
||||
|
||||
1922
bazaar/plugin/gdal/frmts/aigrid/aigccitt.c
Normal file
1922
bazaar/plugin/gdal/frmts/aigrid/aigccitt.c
Normal file
File diff suppressed because it is too large
Load diff
1100
bazaar/plugin/gdal/frmts/aigrid/aigdataset.cpp
Normal file
1100
bazaar/plugin/gdal/frmts/aigrid/aigdataset.cpp
Normal file
File diff suppressed because it is too large
Load diff
479
bazaar/plugin/gdal/frmts/aigrid/aigopen.c
Normal file
479
bazaar/plugin/gdal/frmts/aigrid/aigopen.c
Normal file
|
|
@ -0,0 +1,479 @@
|
|||
/******************************************************************************
|
||||
* $Id: aigopen.c 27044 2014-03-16 23:41:27Z rouault $
|
||||
*
|
||||
* Project: Arc/Info Binary Grid Translator
|
||||
* Purpose: Grid file access cover API for non-GDAL use.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 1999, Frank Warmerdam
|
||||
* Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "aigrid.h"
|
||||
|
||||
CPL_CVSID("$Id: aigopen.c 27044 2014-03-16 23:41:27Z rouault $");
|
||||
|
||||
/************************************************************************/
|
||||
/* AIGOpen() */
|
||||
/************************************************************************/
|
||||
|
||||
AIGInfo_t *AIGOpen( const char * pszInputName, const char * pszAccess )
|
||||
|
||||
{
|
||||
AIGInfo_t *psInfo;
|
||||
char *pszCoverName;
|
||||
|
||||
(void) pszAccess;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* If the pass name ends in .adf assume a file within the */
|
||||
/* coverage has been selected, and strip that off the coverage */
|
||||
/* name. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
pszCoverName = CPLStrdup( pszInputName );
|
||||
if( EQUAL(pszCoverName+strlen(pszCoverName)-4, ".adf") )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = strlen(pszCoverName)-1; i > 0; i-- )
|
||||
{
|
||||
if( pszCoverName[i] == '\\' || pszCoverName[i] == '/' )
|
||||
{
|
||||
pszCoverName[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( i == 0 )
|
||||
strcpy(pszCoverName,".");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Allocate info structure. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
psInfo = (AIGInfo_t *) CPLCalloc(sizeof(AIGInfo_t),1);
|
||||
psInfo->bHasWarned = FALSE;
|
||||
psInfo->pszCoverName = pszCoverName;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read the header file. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( AIGReadHeader( pszCoverName, psInfo ) != CE_None )
|
||||
{
|
||||
CPLFree( pszCoverName );
|
||||
CPLFree( psInfo );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read the extents. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( AIGReadBounds( pszCoverName, psInfo ) != CE_None )
|
||||
{
|
||||
AIGClose( psInfo );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Compute the number of pixels and lines, and the number of */
|
||||
/* tile files. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if (psInfo->dfCellSizeX <= 0 || psInfo->dfCellSizeY <= 0)
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Illegal cell size : %f x %f",
|
||||
psInfo->dfCellSizeX, psInfo->dfCellSizeY );
|
||||
AIGClose( psInfo );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
psInfo->nPixels = (int)
|
||||
((psInfo->dfURX - psInfo->dfLLX + 0.5 * psInfo->dfCellSizeX)
|
||||
/ psInfo->dfCellSizeX);
|
||||
psInfo->nLines = (int)
|
||||
((psInfo->dfURY - psInfo->dfLLY + 0.5 * psInfo->dfCellSizeY)
|
||||
/ psInfo->dfCellSizeY);
|
||||
|
||||
if (psInfo->nPixels <= 0 || psInfo->nLines <= 0)
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Invalid raster dimensions : %d x %d",
|
||||
psInfo->nPixels, psInfo->nLines );
|
||||
AIGClose( psInfo );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (psInfo->nBlockXSize <= 0 || psInfo->nBlockYSize <= 0 ||
|
||||
psInfo->nBlocksPerRow <= 0 || psInfo->nBlocksPerColumn <= 0 ||
|
||||
psInfo->nBlockXSize > INT_MAX / psInfo->nBlocksPerRow ||
|
||||
psInfo->nBlockYSize > INT_MAX / psInfo->nBlocksPerColumn)
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Invalid block characteristics: nBlockXSize=%d, "
|
||||
"nBlockYSize=%d, nBlocksPerRow=%d, nBlocksPerColumn=%d",
|
||||
psInfo->nBlockXSize, psInfo->nBlockYSize,
|
||||
psInfo->nBlocksPerRow, psInfo->nBlocksPerColumn);
|
||||
AIGClose( psInfo );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
psInfo->nTileXSize = psInfo->nBlockXSize * psInfo->nBlocksPerRow;
|
||||
psInfo->nTileYSize = psInfo->nBlockYSize * psInfo->nBlocksPerColumn;
|
||||
|
||||
psInfo->nTilesPerRow = (psInfo->nPixels-1) / psInfo->nTileXSize + 1;
|
||||
psInfo->nTilesPerColumn = (psInfo->nLines-1) / psInfo->nTileYSize + 1;
|
||||
|
||||
if (psInfo->nTilesPerRow > INT_MAX / psInfo->nTilesPerColumn)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_OutOfMemory, "Too many tiles");
|
||||
AIGClose( psInfo );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Setup tile infos, but defer reading of tile data. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
psInfo->pasTileInfo = (AIGTileInfo *)
|
||||
VSICalloc(sizeof(AIGTileInfo),
|
||||
psInfo->nTilesPerRow * psInfo->nTilesPerColumn);
|
||||
if (psInfo->pasTileInfo == NULL)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate tile info array");
|
||||
AIGClose( psInfo );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read the statistics. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( AIGReadStatistics( pszCoverName, psInfo ) != CE_None )
|
||||
{
|
||||
AIGClose( psInfo );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return( psInfo );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* AIGAccessTile() */
|
||||
/************************************************************************/
|
||||
|
||||
CPLErr AIGAccessTile( AIGInfo_t *psInfo, int iTileX, int iTileY )
|
||||
|
||||
{
|
||||
char szBasename[20];
|
||||
char *pszFilename;
|
||||
AIGTileInfo *psTInfo;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Identify our tile. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( iTileX < 0 || iTileX >= psInfo->nTilesPerRow
|
||||
|| iTileY < 0 || iTileY >= psInfo->nTilesPerColumn )
|
||||
{
|
||||
CPLAssert( FALSE );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
psTInfo = psInfo->pasTileInfo + iTileX + iTileY * psInfo->nTilesPerRow;
|
||||
|
||||
if( psTInfo->fpGrid != NULL || psTInfo->bTriedToLoad )
|
||||
return CE_None;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Compute the basename. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( iTileY == 0 )
|
||||
sprintf( szBasename, "w%03d001", iTileX + 1 );
|
||||
else if( iTileY == 1 )
|
||||
sprintf( szBasename, "w%03d000", iTileX + 1 );
|
||||
else
|
||||
sprintf( szBasename, "z%03d%03d", iTileX + 1, iTileY - 1 );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Open the file w001001.adf file itself. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
pszFilename = (char *) CPLMalloc(strlen(psInfo->pszCoverName)+40);
|
||||
sprintf( pszFilename, "%s/%s.adf", psInfo->pszCoverName, szBasename );
|
||||
|
||||
psTInfo->fpGrid = AIGLLOpen( pszFilename, "rb" );
|
||||
psTInfo->bTriedToLoad = TRUE;
|
||||
|
||||
if( psTInfo->fpGrid == NULL )
|
||||
{
|
||||
CPLError( CE_Warning, CPLE_OpenFailed,
|
||||
"Failed to open grid file, assuming region is nodata:\n%s\n",
|
||||
pszFilename );
|
||||
CPLFree( pszFilename );
|
||||
return CE_Warning;
|
||||
}
|
||||
|
||||
CPLFree( pszFilename );
|
||||
pszFilename = NULL;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read the block index file. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
return AIGReadBlockIndex( psInfo, psTInfo, szBasename );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* AIGReadTile() */
|
||||
/************************************************************************/
|
||||
|
||||
CPLErr AIGReadTile( AIGInfo_t * psInfo, int nBlockXOff, int nBlockYOff,
|
||||
GInt32 *panData )
|
||||
|
||||
{
|
||||
int nBlockID;
|
||||
CPLErr eErr;
|
||||
int iTileX, iTileY;
|
||||
AIGTileInfo *psTInfo;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Compute our tile, and ensure it is accessable (open). Then */
|
||||
/* reduce block x/y values to be the block within that tile. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
iTileX = nBlockXOff / psInfo->nBlocksPerRow;
|
||||
iTileY = nBlockYOff / psInfo->nBlocksPerColumn;
|
||||
|
||||
eErr = AIGAccessTile( psInfo, iTileX, iTileY );
|
||||
if( eErr == CE_Failure )
|
||||
return eErr;
|
||||
|
||||
psTInfo = psInfo->pasTileInfo + iTileX + iTileY * psInfo->nTilesPerRow;
|
||||
|
||||
nBlockXOff -= iTileX * psInfo->nBlocksPerRow;
|
||||
nBlockYOff -= iTileY * psInfo->nBlocksPerColumn;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Request for tile from a file which does not exist - treat as */
|
||||
/* all nodata. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( psTInfo->fpGrid == NULL )
|
||||
{
|
||||
int i;
|
||||
for( i = psInfo->nBlockXSize * psInfo->nBlockYSize - 1; i >= 0; i-- )
|
||||
panData[i] = ESRI_GRID_NO_DATA;
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* validate block id. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
nBlockID = nBlockXOff + nBlockYOff * psInfo->nBlocksPerRow;
|
||||
if( nBlockID < 0
|
||||
|| nBlockID >= psInfo->nBlocksPerRow * psInfo->nBlocksPerColumn )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Illegal block requested." );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
if( nBlockID >= psTInfo->nBlocks )
|
||||
{
|
||||
int i;
|
||||
CPLDebug( "AIG",
|
||||
"Request legal block, but from beyond end of block map.\n"
|
||||
"Assuming all nodata." );
|
||||
for( i = psInfo->nBlockXSize * psInfo->nBlockYSize - 1; i >= 0; i-- )
|
||||
panData[i] = ESRI_GRID_NO_DATA;
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read block. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
eErr = AIGReadBlock( psTInfo->fpGrid,
|
||||
psTInfo->panBlockOffset[nBlockID],
|
||||
psTInfo->panBlockSize[nBlockID],
|
||||
psInfo->nBlockXSize, psInfo->nBlockYSize,
|
||||
panData, psInfo->nCellType, psInfo->bCompressed );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Apply floating point post-processing. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( eErr == CE_None && psInfo->nCellType == AIG_CELLTYPE_FLOAT )
|
||||
{
|
||||
float *pafData = (float *) panData;
|
||||
int i, nPixels = psInfo->nBlockXSize * psInfo->nBlockYSize;
|
||||
|
||||
for( i = 0; i < nPixels; i++ )
|
||||
{
|
||||
panData[i] = (int) pafData[i];
|
||||
}
|
||||
}
|
||||
|
||||
return( eErr );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* AIGReadFloatTile() */
|
||||
/************************************************************************/
|
||||
|
||||
CPLErr AIGReadFloatTile( AIGInfo_t * psInfo, int nBlockXOff, int nBlockYOff,
|
||||
float *pafData )
|
||||
|
||||
{
|
||||
int nBlockID;
|
||||
CPLErr eErr;
|
||||
int iTileX, iTileY;
|
||||
AIGTileInfo *psTInfo;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Compute our tile, and ensure it is accessable (open). Then */
|
||||
/* reduce block x/y values to be the block within that tile. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
iTileX = nBlockXOff / psInfo->nBlocksPerRow;
|
||||
iTileY = nBlockYOff / psInfo->nBlocksPerColumn;
|
||||
|
||||
eErr = AIGAccessTile( psInfo, iTileX, iTileY );
|
||||
if( eErr == CE_Failure )
|
||||
return eErr;
|
||||
|
||||
psTInfo = psInfo->pasTileInfo + iTileX + iTileY * psInfo->nTilesPerRow;
|
||||
|
||||
nBlockXOff -= iTileX * psInfo->nBlocksPerRow;
|
||||
nBlockYOff -= iTileY * psInfo->nBlocksPerColumn;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Request for tile from a file which does not exist - treat as */
|
||||
/* all nodata. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( psTInfo->fpGrid == NULL )
|
||||
{
|
||||
int i;
|
||||
for( i = psInfo->nBlockXSize * psInfo->nBlockYSize - 1; i >= 0; i-- )
|
||||
pafData[i] = ESRI_GRID_FLOAT_NO_DATA;
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* validate block id. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
nBlockID = nBlockXOff + nBlockYOff * psInfo->nBlocksPerRow;
|
||||
if( nBlockID < 0
|
||||
|| nBlockID >= psInfo->nBlocksPerRow * psInfo->nBlocksPerColumn )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Illegal block requested." );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
if( nBlockID >= psTInfo->nBlocks )
|
||||
{
|
||||
int i;
|
||||
CPLDebug( "AIG",
|
||||
"Request legal block, but from beyond end of block map.\n"
|
||||
"Assuming all nodata." );
|
||||
for( i = psInfo->nBlockXSize * psInfo->nBlockYSize - 1; i >= 0; i-- )
|
||||
pafData[i] = ESRI_GRID_FLOAT_NO_DATA;
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read block. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
eErr = AIGReadBlock( psTInfo->fpGrid,
|
||||
psTInfo->panBlockOffset[nBlockID],
|
||||
psTInfo->panBlockSize[nBlockID],
|
||||
psInfo->nBlockXSize, psInfo->nBlockYSize,
|
||||
(GInt32 *) pafData, psInfo->nCellType,
|
||||
psInfo->bCompressed );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Perform integer post processing. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( eErr == CE_None && psInfo->nCellType == AIG_CELLTYPE_INT )
|
||||
{
|
||||
GUInt32 *panData = (GUInt32 *) pafData;
|
||||
int i, nPixels = psInfo->nBlockXSize * psInfo->nBlockYSize;
|
||||
|
||||
for( i = 0; i < nPixels; i++ )
|
||||
{
|
||||
pafData[i] = (float) panData[i];
|
||||
}
|
||||
}
|
||||
|
||||
return( eErr );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* AIGClose() */
|
||||
/************************************************************************/
|
||||
|
||||
void AIGClose( AIGInfo_t * psInfo )
|
||||
|
||||
{
|
||||
int nTileCount = psInfo->nTilesPerRow * psInfo->nTilesPerColumn;
|
||||
int iTile;
|
||||
|
||||
for( iTile = 0; iTile < nTileCount; iTile++ )
|
||||
{
|
||||
if( psInfo->pasTileInfo[iTile].fpGrid )
|
||||
{
|
||||
VSIFCloseL( psInfo->pasTileInfo[iTile].fpGrid );
|
||||
|
||||
CPLFree( psInfo->pasTileInfo[iTile].panBlockOffset );
|
||||
CPLFree( psInfo->pasTileInfo[iTile].panBlockSize );
|
||||
}
|
||||
}
|
||||
|
||||
CPLFree( psInfo->pasTileInfo );
|
||||
CPLFree( psInfo->pszCoverName );
|
||||
CPLFree( psInfo );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* AIGLLOpen() */
|
||||
/* */
|
||||
/* Low level fopen() replacement that will try provided, and */
|
||||
/* upper cased versions of file names. */
|
||||
/************************************************************************/
|
||||
|
||||
VSILFILE *AIGLLOpen( const char *pszFilename, const char *pszAccess )
|
||||
|
||||
{
|
||||
VSILFILE *fp;
|
||||
|
||||
fp = VSIFOpenL( pszFilename, pszAccess );
|
||||
if( fp == NULL )
|
||||
{
|
||||
char *pszUCFilename = CPLStrdup(pszFilename);
|
||||
int i;
|
||||
|
||||
for( i = strlen(pszUCFilename)-1;
|
||||
pszUCFilename[i] != '/' && pszUCFilename[i] != '\\';
|
||||
i-- )
|
||||
{
|
||||
pszUCFilename[i] = (char) toupper(pszUCFilename[i]);
|
||||
}
|
||||
|
||||
fp = VSIFOpenL( pszUCFilename, pszAccess );
|
||||
|
||||
CPLFree( pszUCFilename );
|
||||
}
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
135
bazaar/plugin/gdal/frmts/aigrid/aigrid.h
Normal file
135
bazaar/plugin/gdal/frmts/aigrid/aigrid.h
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/******************************************************************************
|
||||
* $Id: aigrid.h 22159 2011-04-14 18:18:54Z warmerdam $
|
||||
*
|
||||
* Project: Arc/Info Binary Grid Translator
|
||||
* Purpose: Grid file access include file.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 1999, Frank Warmerdam
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _AIGRID_H_INCLUDED
|
||||
#define _AIGRID_H_INCLUDED
|
||||
|
||||
#include "cpl_conv.h"
|
||||
|
||||
CPL_C_START
|
||||
|
||||
#define ESRI_GRID_NO_DATA -2147483647
|
||||
/*#define ESRI_GRID_FLOAT_NO_DATA -340282306073709652508363335590014353408.0 */
|
||||
#define ESRI_GRID_FLOAT_NO_DATA -340282346638528859811704183484516925440.0
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Grid Instance */
|
||||
/* ==================================================================== */
|
||||
|
||||
typedef struct {
|
||||
int nBlocks;
|
||||
GUInt32 *panBlockOffset;
|
||||
int *panBlockSize;
|
||||
|
||||
VSILFILE *fpGrid; /* the w001001.adf file */
|
||||
int bTriedToLoad;
|
||||
} AIGTileInfo;
|
||||
|
||||
typedef struct {
|
||||
/* Private information */
|
||||
|
||||
AIGTileInfo *pasTileInfo;
|
||||
|
||||
int bHasWarned;
|
||||
|
||||
/* public information */
|
||||
|
||||
char *pszCoverName; /* path of coverage directory */
|
||||
|
||||
GInt32 nCellType;
|
||||
GInt32 bCompressed;
|
||||
|
||||
#define AIG_CELLTYPE_INT 1
|
||||
#define AIG_CELLTYPE_FLOAT 2
|
||||
|
||||
GInt32 nBlockXSize;
|
||||
GInt32 nBlockYSize;
|
||||
|
||||
GInt32 nBlocksPerRow;
|
||||
GInt32 nBlocksPerColumn;
|
||||
|
||||
int nTileXSize;
|
||||
int nTileYSize;
|
||||
|
||||
int nTilesPerRow;
|
||||
int nTilesPerColumn;
|
||||
|
||||
double dfLLX;
|
||||
double dfLLY;
|
||||
double dfURX;
|
||||
double dfURY;
|
||||
|
||||
double dfCellSizeX;
|
||||
double dfCellSizeY;
|
||||
|
||||
int nPixels;
|
||||
int nLines;
|
||||
|
||||
double dfMin;
|
||||
double dfMax;
|
||||
double dfMean;
|
||||
double dfStdDev;
|
||||
|
||||
} AIGInfo_t;
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Private APIs */
|
||||
/* ==================================================================== */
|
||||
|
||||
CPLErr AIGAccessTile( AIGInfo_t *psInfo, int iTileX, int iTileY );
|
||||
CPLErr AIGReadBlock( VSILFILE * fp, GUInt32 nBlockOffset, int nBlockSize,
|
||||
int nBlockXSize, int nBlockYSize, GInt32 * panData,
|
||||
int nCellType, int bCompressed );
|
||||
|
||||
CPLErr AIGReadHeader( const char *, AIGInfo_t * );
|
||||
CPLErr AIGReadBlockIndex( AIGInfo_t *, AIGTileInfo *,
|
||||
const char *pszBasename );
|
||||
CPLErr AIGReadBounds( const char *, AIGInfo_t * );
|
||||
CPLErr AIGReadStatistics( const char *, AIGInfo_t * );
|
||||
|
||||
CPLErr DecompressCCITTRLETile( unsigned char *pabySrcData, int nSrcBytes,
|
||||
unsigned char *pabyDstData, int nDstBytes,
|
||||
int nBlockXSize, int nBlockYSize );
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Public APIs */
|
||||
/* ==================================================================== */
|
||||
|
||||
AIGInfo_t *AIGOpen( const char *, const char * );
|
||||
|
||||
CPLErr AIGReadTile( AIGInfo_t *, int, int, GInt32 * );
|
||||
CPLErr AIGReadFloatTile( AIGInfo_t *, int, int, float * );
|
||||
|
||||
void AIGClose( AIGInfo_t * );
|
||||
|
||||
VSILFILE *AIGLLOpen( const char *, const char * );
|
||||
|
||||
CPL_C_END
|
||||
|
||||
#endif /* ndef _AIGRID_H_INCLUDED */
|
||||
790
bazaar/plugin/gdal/frmts/aigrid/aigrid_format.html
Normal file
790
bazaar/plugin/gdal/frmts/aigrid/aigrid_format.html
Normal file
|
|
@ -0,0 +1,790 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<title>Arc/Info Binary Grid Format</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff">
|
||||
|
||||
<h1>Arc/Info Binary Grid Format</h1>
|
||||
|
||||
<i>by <a href="http://pobox.com/~warmerdam">Frank Warmerdam</a></i>
|
||||
(<a href="mailto:warmerdam@pobox.com">warmerdam@pobox.com</a>)<p>
|
||||
|
||||
The Arc/Info Binary Grid format is the internal working format of the
|
||||
Arc/Info Grid product. It is also usable and creatable within the
|
||||
spatial analyst component of ArcView. It is a tiled (blocked) format with run
|
||||
length compression capable of holding raster data of up to 4 byte integers
|
||||
or 4 byte floating data. <p>
|
||||
|
||||
This format should not be confused with the Arc/Info ASCII Grid format
|
||||
which is the interchange format for grids. Files can be converted between
|
||||
binary and ASCII format with the GRIDASCII and ASCIIGRID commands in
|
||||
Arc/Info. This format is also different than the flat binary raster
|
||||
output of the GRIDFLOAT command. The Arc/Info binary float, and ASCII
|
||||
formats are also accessable from within ArcView.<p>
|
||||
|
||||
This format should also not be confused with what I know as ESRI BIL format.
|
||||
This is really a standard ESRI way of creating a header file (.HDR)
|
||||
describing the data layout a binary raster file containing raster data.<p>
|
||||
|
||||
<!--------------------------------------------------------------------------->
|
||||
|
||||
<h2>Version</h2>
|
||||
|
||||
I am not sure yet how the versions work for grid files. I have been
|
||||
working primarily with grid files generated by ArcView 3.x, and it's associated
|
||||
gridio API. The hdr.adf files I have examined start with the string
|
||||
<b>GRID1.2</b> for what that's worth. Certainly the file naming conventions
|
||||
seem to follow the Arc/Info 7.x conventions rather than that of earlier
|
||||
versions.<p>
|
||||
|
||||
<!--------------------------------------------------------------------------->
|
||||
|
||||
<h2>File Set</h2>
|
||||
|
||||
A grid coverage actually consists of a number of files. A grid normally
|
||||
lives in it's own directory named after the grid. For instance, the
|
||||
grid <b>nwgrd1</b> lives in the directory <b>nwgrd1</b>, and has the following
|
||||
component files:<p>
|
||||
|
||||
<pre>
|
||||
-rwxr--r-- 1 warmerda users 32 Jan 22 16:07 nwgrd1/dblbnd.adf
|
||||
-rwxr--r-- 1 warmerda users 308 Jan 22 16:07 nwgrd1/hdr.adf
|
||||
-rwxr--r-- 1 warmerda users 32 Jan 22 16:07 nwgrd1/sta.adf
|
||||
-rwxr--r-- 1 warmerda users 2048 Jan 22 16:07 nwgrd1/vat.adf
|
||||
-rwxr--r-- 1 warmerda users 187228 Jan 22 16:07 nwgrd1/w001001.adf
|
||||
-rwxr--r-- 1 warmerda users 6132 Jan 22 16:07 nwgrd1/w001001x.adf
|
||||
</pre>
|
||||
|
||||
Sometimes datasets will also include a prj.adf files containing the projection
|
||||
definition in the usual ESRI format. Grids also normally have associated
|
||||
tables in the info directory. This is beyond the scope of my discussion
|
||||
for now.<p>
|
||||
|
||||
The files have the following roles:
|
||||
|
||||
<ul>
|
||||
|
||||
<li> <a href="#dblbnd">dblbnd.adf</a>: Contains the bounds
|
||||
(LLX, LLY, URX, URY) of the portion of utilized portion of the grid.<p>
|
||||
|
||||
<li> <a href="#hdr.adf">hdr.adf</a>: This is the header, and contains
|
||||
information on the tile sizes, and number of tiles in the dataset. It also
|
||||
contains assorted other information I have yet to identify.<p>
|
||||
|
||||
<li> <a href="#sta">sta.adf</a>: This contains raster statistics. In
|
||||
particular, the raster min, max, mean and standard deviation.<p>
|
||||
|
||||
<li> <b>vat.adf</b>: This relates to the value attribute table. This is
|
||||
the table corresponding integer raster values with a set of attributes. I
|
||||
presume it is really just a pointer into info in a manner similar to the
|
||||
pat.adf file in a vector coverage, but I haven't investigated yet. <p>
|
||||
|
||||
<li> <a href="#w001001">w001001.adf</a>:
|
||||
This is the file containing the actual raster data.
|
||||
<p>
|
||||
|
||||
<li> <a href="#w001001x">w001001x.adf</a>:
|
||||
This is an index file containing pointers to
|
||||
each of the tiles in the w001001.adf raster file.<p>
|
||||
|
||||
</ul>
|
||||
|
||||
<!--------------------------------------------------------------------------->
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="dblbnd">dblbnd.adf - Georef Bounds</a></h2>
|
||||
|
||||
Fields:<p>
|
||||
|
||||
<table border>
|
||||
<th>Start Byte
|
||||
<th># of Bytes
|
||||
<th>Format
|
||||
<th>Name
|
||||
<th>Description
|
||||
|
||||
<tr>
|
||||
<td> 0
|
||||
</td><td> 8
|
||||
</td><td> MSB double
|
||||
</td><td> D_LLX
|
||||
</td><td> Lower left X (easting) of the grid. Generally -0.5 for an
|
||||
ungeoreferenced grid.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 8
|
||||
</td><td> 8
|
||||
</td><td> MSB double
|
||||
</td><td> D_LLY
|
||||
</td><td> Lower left Y (northing) of the grid. Generally -0.5 for an
|
||||
ungeoreferenced grid.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 16
|
||||
</td><td> 8
|
||||
</td><td> MSB double
|
||||
</td><td> D_URX
|
||||
</td><td> Upper right X (easting) of the grid. Generally #Pixels-0.5 for an
|
||||
ungeoreferenced grid.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 24
|
||||
</td><td> 8
|
||||
</td><td> MSB double
|
||||
</td><td> D_URY
|
||||
</td><td> Upper right Y (northing) of the grid. Generally #Lines-0.5 for an
|
||||
ungeoreferenced grid.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
This file is always 32 bytes long. The bounds apply to the portion of the
|
||||
grid that is in use, not the whole thing.<p>
|
||||
|
||||
<!--------------------------------------------------------------------------->
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="w001001x">w001001x.adf - Tile Index</a></h2>
|
||||
|
||||
This is a binary dump of the first 320 bytes of a w001001x.adf
|
||||
file. <p>
|
||||
|
||||
<pre>
|
||||
0: 0000270A FFFFFC14 00000000 00000000 ~~'~~~~~~~~~~~~~
|
||||
16: 00000000 00000000 00000BFA 00000000 ~~~~~~~~~~~~~~~~
|
||||
32: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
|
||||
48: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
|
||||
64: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
|
||||
80: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
|
||||
96: 00000000 00000032 00000202 00000235 ~~~~~~~2~~~~~~~5
|
||||
112: 000001D4 0000040A 00000000 0000040B ~~~~~~~~~~~~~~~~
|
||||
128: 00000000 0000040C 00000000 0000040D ~~~~~~~~~~~~~~~~
|
||||
144: 00000000 0000040E 00000000 0000040F ~~~~~~~~~~~~~~~~
|
||||
160: 00000000 00000410 00000202 00000613 ~~~~~~~~~~~~~~~~
|
||||
176: 000001D4 000007E8 00000000 000007E9 ~~~~~~~~~~~~~~~~
|
||||
192: 00000000 000007EA 00000000 000007EB ~~~~~~~~~~~~~~~~
|
||||
208: 00000000 000007EC 00000000 000007ED ~~~~~~~~~~~~~~~~
|
||||
224: 00000000 000007EE 00000202 000009F1 ~~~~~~~~~~~~~~~~
|
||||
240: 000001D4 00000BC6 00000000 00000BC7 ~~~~~~~~~~~~~~~~
|
||||
256: 00000000 00000BC8 00000000 00000BC9 ~~~~~~~~~~~~~~~~
|
||||
272: 00000000 00000BCA 00000000 00000BCB ~~~~~~~~~~~~~~~~
|
||||
288: 00000000 00000BCC 00000202 00000DCF ~~~~~~~~~~~~~~~~
|
||||
304: 000001D4 00000FA4 00000000 00000FA5 ~~~~~~~~~~~~~~~~
|
||||
</pre>
|
||||
|
||||
Fields:<p>
|
||||
|
||||
<table border>
|
||||
<th>Start Byte
|
||||
<th># of Bytes
|
||||
<th>Format
|
||||
<th>Description
|
||||
|
||||
<tr>
|
||||
<td> 0
|
||||
</td><td> 8
|
||||
</td><td>
|
||||
</td><td> Magic Number (always hex 00 00 27 0A FF FF ** **, usually ending in FC 14, FB F8 or FC 08).
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 8
|
||||
</td><td> 16
|
||||
</td><td>
|
||||
</td><td> zero fill
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 24
|
||||
</td><td> 4
|
||||
</td><td> MSB Int32
|
||||
</td><td> Size of whole file in shorts (multiply by two
|
||||
to get file size in bytes).
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 28
|
||||
</td><td> 72
|
||||
</td><td>
|
||||
</td><td> zero fill
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 100 + <b>t</b>*8
|
||||
</td><td> 4
|
||||
</td><td> MSB Int32
|
||||
</td><td> Offset to tile <b>t</b> in w001001.adf measured in two byte
|
||||
shorts.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 104 + <b>t</b>*8
|
||||
</td><td> 4
|
||||
</td><td> MSB Int32
|
||||
</td><td> Size of tile <b>t</b> in 2 byte shorts.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<!--------------------------------------------------------------------------->
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="sta">sta.adf - Raster Statistics</a></h2>
|
||||
|
||||
Fields:<p>
|
||||
|
||||
<table border>
|
||||
<th>Start Byte
|
||||
<th># of Bytes
|
||||
<th>Format
|
||||
<th>Name
|
||||
<th>Description
|
||||
|
||||
<tr>
|
||||
<td> 0
|
||||
</td><td> 8
|
||||
</td><td> MSB double
|
||||
</td><td> SMin
|
||||
</td><td> Minimum value of a raster cell in this grid.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 8
|
||||
</td><td> 8
|
||||
</td><td> MSB double
|
||||
</td><td> SMax
|
||||
</td><td> Maximum value of a raster cell in this grid.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 16
|
||||
</td><td> 8
|
||||
</td><td> MSB double
|
||||
</td><td> SMean
|
||||
</td><td> Mean value of a raster cells in this grid.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 24
|
||||
</td><td> 8
|
||||
</td><td> MSB double
|
||||
</td><td> SStdDev
|
||||
</td><td> Standard deviation of raster cells in this grid.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
This file is always 32 bytes long. <p>
|
||||
|
||||
<!--------------------------------------------------------------------------->
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="w001001">w001001.adf - Raster Data</a></h2>
|
||||
|
||||
This is a binary dump of the first 320 bytes of a w001001.adf
|
||||
file.<p>
|
||||
|
||||
<pre>
|
||||
0: 0000270A FFFFFC14 00000000 00000000 ~~'~~~~~~~~~~~~~
|
||||
16: 00000000 00000000 00016DAE 00000000 ~~~~~~~~~~m~~~~~
|
||||
32: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
|
||||
48: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
|
||||
64: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
|
||||
80: 00000000 00000000 00000000 00000000 ~~~~~~~~~~~~~~~~
|
||||
96: 00000000 02020800 00373D42 5C5A4D31 ~~~~~~~~~7=B\ZM1
|
||||
112: 200A0108 0E1D4F89 9C9A9392 8C7E6653 ~~~~~O~~~~~~~fS
|
||||
128: 5151596D 83919290 868A8B87 807A7A7B QQYm~~~~~~~~~zz{
|
||||
144: 7C7A766F 64481D00 0406305F 6B6C6A5B |zvodH~~~~0_klj[
|
||||
160: 5D53513C 2D2D2732 24293F54 40354C55 ]SQ<--'2$)?T@5LU
|
||||
176: 67686258 514E4943 5859534A 41394D70 ghbXQNICXYSJA9Mp
|
||||
192: 75665659 66625A63 737A848E 9090979F ufVYfbZcsz~~~~~~
|
||||
208: 9F908C8F 8F96998E 8778685B 53536274 ~~~~~~~~~xh[SSbt
|
||||
224: 747B838A 8A8C8F92 8D979B94 8C8D9294 t{~~~~~~~~~~~~~~
|
||||
240: 8D8D8D8D 8C8B8989 8B8E908F 8E8E9092 ~~~~~~~~~~~~~~~~
|
||||
256: 90929394 989C9891 92939698 9B9B9C9C ~~~~~~~~~~~~~~~~
|
||||
272: 8E8E8F8F 8E8E8F90 898E918F 8B8A8E93 ~~~~~~~~~~~~~~~~
|
||||
288: 8B8D9093 94918C86 838DA1BC B7CEC9B0 ~~~~~~~~~~~~~~~~
|
||||
304: D4B0BB96 A0929E99 9797999B 9D9C9C9B ~~~~~~~~~~~~~~~~
|
||||
</pre>
|
||||
|
||||
Fields:<p>
|
||||
|
||||
<table border>
|
||||
<th>Start Byte
|
||||
<th># of Bytes
|
||||
<th>Format
|
||||
<th>Name
|
||||
<th>Description
|
||||
|
||||
<tr>
|
||||
<td> 0
|
||||
</td><td> 8
|
||||
</td><td>
|
||||
</td><td> RMagic
|
||||
</td><td> Magic Number (always hex 00 00 27 0A FF FF ** **, usually ending in FC 14, FB F8 or FC 08).
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 8
|
||||
</td><td> 16
|
||||
</td><td>
|
||||
</td><td>
|
||||
</td><td> zero fill
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 24
|
||||
</td><td> 4
|
||||
</td><td> MSB Int32
|
||||
</td><td> RFileSize
|
||||
</td><td> Size of whole file in shorts (multiply by two
|
||||
to get file size in bytes).
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 28
|
||||
</td><td> 72
|
||||
</td><td>
|
||||
</td><td>
|
||||
</td><td> zero fill
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 100, ...
|
||||
</td><td> 2
|
||||
</td><td> MSB Int16
|
||||
</td><td> RTileSize
|
||||
</td><td> Size of this tiles data measured in shorts. This matches the size
|
||||
in the index file, and does not include the tile size itself. The next
|
||||
tile starts <b>2*n+2</b> bytes after the start of this tile, where <b>n</b>
|
||||
is the value of this field.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 102, ...
|
||||
</td><td> 1
|
||||
</td><td> byte
|
||||
</td><td> RTileType
|
||||
</td><td> Tile type code indicating the organization of the following
|
||||
data (integer coverages only).
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> 103, ...
|
||||
</td><td> 1
|
||||
</td><td> byte
|
||||
</td><td> RMinSize
|
||||
</td><td> Number of bytes following to form the minimum value for the tile
|
||||
(integer coverages only).
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 104, ...
|
||||
</td><td> (RMinSize bytes)
|
||||
</td><td> MSB Int (var size)
|
||||
</td><td> RMin
|
||||
</td><td> The minimum value pixels for this tile. This number is added
|
||||
to the pixel values for each pixel in this tile (integer coverages only).
|
||||
I must stress that if RMinSize is less than 4 this is still a signed quantity.
|
||||
For instance, if RMinSize is 2, the value is 65536 - byte0*256 - byte1 if
|
||||
byte0 is > 127.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 104+RMinSize, ...
|
||||
</td><td> RTileSize*2 - 3 - RMinSize
|
||||
</td><td> variable
|
||||
</td><td> RTileData
|
||||
</td><td> The data for this tile. Format varies according to RTileType
|
||||
for integer coverages.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<p>
|
||||
|
||||
The fields RTileSize, RTileType, RMinSize, RMin, and RTileData occur in the
|
||||
file for each tile of data present. They are usually packed one after the
|
||||
other, but this isn't necessarily guaranteed. The index file (w001001x.adf)
|
||||
should be used to establish the tile locations. Note that tiles that
|
||||
appear in the index file with a size of zero will appear as just two
|
||||
bytes (zeros) for the RTileSize for that tile.<p>
|
||||
|
||||
<!------------------------------------------>
|
||||
|
||||
<h3>Raster Size</h3>
|
||||
|
||||
The size of a the grid isn't as easy to deduce as one might expect.
|
||||
The hdr.adf file contains the HTilesPerRow, HTilesPerColumn,
|
||||
HTileXSize, and HTileYSize fields which imply a particular raster
|
||||
space. However, it seems that this is created much larger than
|
||||
necessary to hold the users raster data. I have created 3x1 rasters
|
||||
which resulted in the standard 8x512 tiles of 256x4 pixels each.<p>
|
||||
|
||||
It seems that the user portion of the raster has to be computed
|
||||
based on the georeferenced bounds in the dblbnd.adf file (assumed
|
||||
to be anchored at the top left of the total raster space), and
|
||||
the HPixelSizeX, and HPixelSizeY fields from hdr.adf.<p>
|
||||
|
||||
<b> #Pixels = (D_URX - D_LRX) / HPixelSizeX</b><p>
|
||||
<b> #Lines = (D_URY - D_LRY) / HPixelSizeY</b><p>
|
||||
|
||||
Based on this number of pixels and lines, it is possible to establish
|
||||
what portion out of the top left of the raster is really <i>of
|
||||
interest</i>. All regions outside this appear to empty tiles,
|
||||
or filled with no data markers.<p>
|
||||
|
||||
<!------------------------------------------>
|
||||
|
||||
<h3>RTileType/RTileData</h3>
|
||||
|
||||
Each tile contains HBlockXSize * HBlockYSize pixels of data. For floating
|
||||
point and uncompressed integer files the data is just the tile size (in two
|
||||
bytes) followed by the pixel data as 4 byte MSB order IEEE floating point
|
||||
words. For compressed integer
|
||||
tiles it is necessary to interpret the RTileType to establish the details
|
||||
of the tile organization:
|
||||
|
||||
|
||||
<h4>RTileType = 0x00 (constant block)</h4>
|
||||
|
||||
All pixels take the value of the RMin. Data is ignored. It appears there is
|
||||
sometimes a bit of meaningless data (up to four bytes) in the block.<p>
|
||||
|
||||
<h4>RTileType = 0x01 (raw 1bit data)</h4>
|
||||
|
||||
One full tile worth of data pixel values follows the RMin field, with
|
||||
1bit per pixel.<p>
|
||||
|
||||
<h4>RTileType = 0x04 (raw 4bit data)</h4>
|
||||
|
||||
One full tiles worth of data pixel values follows the RMin field, with
|
||||
4 bits per pixel. The high order four bits of a byte comes before the low
|
||||
order four bits.<p>
|
||||
|
||||
<h4>RTileType = 0x08 (raw byte data)</h4>
|
||||
|
||||
One full tiles worth of data pixel values (one byte per pixel) follows the
|
||||
RMin field.<p>
|
||||
|
||||
<h4>RTileType = 0x10 (raw 16bit data)</h4>
|
||||
|
||||
One full tiles worth of data pixel values follows the RMin field, with
|
||||
16 bits per pixel (MSB).<p>
|
||||
|
||||
<h4>RTileType = 0x20 (raw 32bit data)</h4>
|
||||
|
||||
One full tiles worth of data pixel values follows the RMin field, with
|
||||
32 bits per pixel (MSB).<p>
|
||||
|
||||
<h4>RTileType = 0xCF (16 bit literal runs/nodata runs)</h4>
|
||||
|
||||
The data is organized in a series of runs. Each run starts with a marker
|
||||
which should be interpreted as:
|
||||
|
||||
<ul>
|
||||
<li> <b>Marker < 128</b>: The marker is followed by <b>Marker</b> pixels of
|
||||
literal data with two MSB bytes per pixel. <p>
|
||||
|
||||
<li> <b>Marker > 127</b>: The marker indicates that <b>256-Marker</b> pixels
|
||||
of <i>no data</i> pixels should be put into the output stream. No data
|
||||
(other than the next marker) follows this marker.
|
||||
|
||||
</ul>
|
||||
|
||||
<h4>RTileType = 0xD7 (literal runs/nodata runs)</h4>
|
||||
|
||||
The data is organized in a series of runs. Each run starts with a marker
|
||||
which should be interpreted as:
|
||||
|
||||
<ul>
|
||||
<li> <b>Marker < 128</b>: The marker is followed by <b>Marker</b> pixels of
|
||||
literal data with one byte per pixel. <p>
|
||||
|
||||
<li> <b>Marker > 127</b>: The marker indicates that <b>256-Marker</b> pixels
|
||||
of <i>no data</i> pixels should be put into the output stream. No data
|
||||
(other than the next marker) follows this marker.
|
||||
|
||||
</ul>
|
||||
|
||||
<h4>RTileType = 0xDF (RMin runs/nodata runs)</h4>
|
||||
|
||||
The data is organized in a series of runs. Each run starts with a marker
|
||||
which should be interpreted as:
|
||||
|
||||
<ul>
|
||||
<li> <b>Marker < 128</b>: The marker is followed by <b>Marker</b> pixels of
|
||||
literal data with one byte per pixel. <p>
|
||||
|
||||
<li> <b>Marker > 127</b>: The marker indicates that <b>256-Marker</b> pixels
|
||||
of <i>no data</i> pixels should be put into the output stream. No data
|
||||
(other than the next marker) follows this marker.
|
||||
|
||||
</ul>
|
||||
|
||||
This is similar to 0xD7, except that the data size is zero bytes instead of
|
||||
1, so only RMin values are inserted into the output stream.<p>
|
||||
|
||||
<h4>RTileType = 0xE0 (run length encoded 32bit)</h4>
|
||||
|
||||
The data is organized in a series of runs. Each run starts with a marker
|
||||
which should be interpreted as a <b>count</b>. The four bytes following the
|
||||
count should be interpreted as an MSB Int32 <b>value</b>. They indicate
|
||||
that <b>count</b> pixels of <b>value</b> should be inserted into the output
|
||||
stream.<p>
|
||||
|
||||
<h4>RTileType = 0xF0 (run length encoded 16bit)</h4>
|
||||
|
||||
The data is organized in a series of runs. Each run starts with a marker
|
||||
which should be interpreted as a <b>count</b>. The two bytes following the
|
||||
count should be interpreted as an MSB Int16 <b>value</b>. They indicate
|
||||
that <b>count</b> pixels of <b>value</b> should be inserted into the output
|
||||
stream.<p>
|
||||
|
||||
<h4>RTileType = 0xFC/0xF8 (run length encoded 8bit)</h4>
|
||||
|
||||
The data is organized in a series of runs. Each run starts with a marker
|
||||
which should be interpreted as a <b>count</b>. The following byte is the
|
||||
<b>value</b>. They indicate
|
||||
that <b>count</b> pixels of <b>value</b> should be inserted into the output
|
||||
stream.<p>
|
||||
|
||||
The intepretation is the same for 0xFC, and 0xF8. I believe that 0xFC has
|
||||
a lower dynamic (2 bit) range than 0xF8 (4 or 8 bit).<p>
|
||||
|
||||
<h4>RTileType = 0xFF (RMin CCITT RLE 1Bit)</h4>
|
||||
|
||||
The data stream for this file is CCITT RLE (G1 fax) compressed. The
|
||||
format is complex but source is provided with the sample program (derived
|
||||
from libtiff) for reading it. The result of uncompressing is 1bit data so
|
||||
which the RMin value should be added.<p>
|
||||
|
||||
|
||||
<!--------------------------------------------------------------------------->
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="hdr.adf">hdr.adf - Header</a></h2>
|
||||
|
||||
This is a binary dump of the first 308 bytes of a hdr.adf
|
||||
file.<p>
|
||||
|
||||
<pre>
|
||||
0: 47524944 312E3200 00000000 FFFFFFFF GRID1.2~~~~~~~~~
|
||||
16: 00000001 00000000 0000164E 3F800000 ~~~~~~~~~~~N?~~~
|
||||
32: 00000F00 F6180000 90060000 3603D601 ~~~~~~~~~~~~6~~~
|
||||
48: 6403E301 01000000 7620F808 43012B03 d~~~~~~~v ~~C~+~
|
||||
64: D6019903 E3012B03 D6019903 E301F7BF ~~~~~~+~~~~~~~~~
|
||||
80: 00007406 6E1FC2A4 7A370D00 0B004200 ~~t~n~~~z7~~~~B~
|
||||
96: 4E1654A4 00000000 00000000 00000000 N~T~~~~~~~~~~~~~
|
||||
112: 34A5A89D FF0414A5 A70F0002 00000000 4~~~~~~~~~~~~~~~
|
||||
128: 00000000 3C0B5F06 A8C05F06 08005AC0 ~~~~<~_~~~_~~~Z~
|
||||
144: 0A00E101 36035AC0 72085F06 FAA42F3C ~~~~6~Z~r~_~~~/<
|
||||
160: 0A001667 02000E00 A80B0200 08370200 ~~~g~~~~~~~~~7~~
|
||||
176: 0CA00200 9C0B0200 04370200 36A0E436 ~~~~~~~~~7~~6~~6
|
||||
192: 84000000 36A00200 5F063EA5 0883FF04 ~~~~6~~~_~>~~~~~
|
||||
208: 00008400 00000010 BD810200 5F010000 ~~~~~~~~~~~~_~~~
|
||||
224: 670E0000 5F01560E 4C4F0001 84008CA5 g~~~_~V~LO~~~~~~
|
||||
240: 28008F01 1000E00A 6628F7BF 4076FF04 (~~~~~~~f(~~@v~~
|
||||
256: 3FF00000 00000000 3FF00000 00000000 ?~~~~~~~?~~~~~~~
|
||||
272: C08FFC00 00000000 C0A1BF00 00000000 ~~~~~~~~~~~~~~~~
|
||||
288: 00000008 00000200 00000100 00000001 ~~~~~~~~~~~~~~~~
|
||||
304: 00000004 ~~~~
|
||||
</pre>
|
||||
|
||||
Fields:<p>
|
||||
|
||||
<table border>
|
||||
<th>Start Byte
|
||||
<th># of Bytes
|
||||
<th>Format
|
||||
<th>Name
|
||||
<th>Description
|
||||
|
||||
<tr>
|
||||
<td> 0
|
||||
</td><td> 8
|
||||
</td><td> Char
|
||||
</td><td> HMagic
|
||||
</td><td> Magic Number - always "GRID1.2\0"
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 8
|
||||
</td><td> 8
|
||||
</td><td>
|
||||
</td><td>
|
||||
</td><td> assorted data, I don't know the purpose.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 16
|
||||
</td><td> 4
|
||||
</td><td> MSB Int32
|
||||
</td><td> HCellType
|
||||
</td><td> 1 = int cover, 2 = float cover.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 20
|
||||
</td><td> 4
|
||||
</td><td> MSB Int32
|
||||
</td><td> CompFlag
|
||||
</td><td> 0 = compressed, 1 = uncompressed
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 24
|
||||
</td><td> 232
|
||||
</td><td>
|
||||
</td><td>
|
||||
</td><td> assorted data, I don't know the purpose.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 256
|
||||
</td><td> 8
|
||||
</td><td> MSB Double
|
||||
</td><td> HPixelSizeX
|
||||
</td><td> Width of a pixel in georeferenced coordinates. Generally 1.0
|
||||
for ungeoreferenced rasters.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 264
|
||||
</td><td> 8
|
||||
</td><td> MSB Double
|
||||
</td><td> HPixelSizeY
|
||||
</td><td> Height of a pixel in georeferenced coordinates. Generally 1.0
|
||||
for ungeoreferenced rasters.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 272
|
||||
</td><td> 8
|
||||
</td><td> MSB Double
|
||||
</td><td> XRef
|
||||
</td><td> dfLLX-(nBlocksPerRow*nBlockXSize*dfCellSizeX)/2.0
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 280
|
||||
</td><td> 8
|
||||
</td><td> MSB Double
|
||||
</td><td> YRef
|
||||
</td><td> dfURY-(3*nBlocksPerColumn*nBlockYSize*dfCellSizeY)/2.0
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 288
|
||||
</td><td> 4
|
||||
</td><td> MSB Int32
|
||||
</td><td> HTilesPerRow
|
||||
</td><td> The width of the file in tiles (often 8 for files of
|
||||
less than 2K in width).
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 292
|
||||
</td><td> 4
|
||||
</td><td> MSB Int32
|
||||
</td><td> HTilesPerColumn
|
||||
</td><td> The height of the file in tiles. Note this may be much more than
|
||||
the number of tiles actually represented in the index file.<p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 296
|
||||
</td><td> 4
|
||||
</td><td> MSB Int32
|
||||
</td><td> HTileXSize
|
||||
</td><td> The width of a file in pixels. Normally 256. </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 300
|
||||
</td><td> 4
|
||||
</td><td> MSB Int32
|
||||
</td><td>
|
||||
</td><td> Unknown, usually 1.
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 304
|
||||
</td><td> 4
|
||||
</td><td> MSB Int32
|
||||
</td><td> HTileYSize
|
||||
</td><td> Height of a tile in pixels, usually 4.
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<!--------------------------------------------------------------------------->
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Acknowledgements</h2>
|
||||
|
||||
I would like to thank <a href="http://www.geosoft.com/">Geosoft Inc.</a>
|
||||
for partial funding of my research into this
|
||||
format. I would also like to thank:<p>
|
||||
|
||||
<ul>
|
||||
<li> Kenneth R. McVay for providing the statistics file format.
|
||||
<li> Noureddine Farah of ThinkSpace who dug up lots of datasets that caused
|
||||
problems.
|
||||
<li> Luciano Fonseca who worked out RTileType 0x01.
|
||||
<li> Martin Manningham of Global Geomatics for additional problem sample files.
|
||||
<li> Harry Anderson of EDX Engineering, for showing me that floating point
|
||||
tiles don't have RTileType.
|
||||
<li> Ian Turton for supplying a sample files demonstrating the need to be
|
||||
careful with the sign of "short" RMin values.
|
||||
<li> Duncan Chaundy at PCI for poking hard till I finally deduced 0xFF tiles.
|
||||
<li> Stephen Cheeseman of GeoSoft for yet more problem files.
|
||||
<li> Geoffrey Williams for a files demonstrating tile type 0x20.
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
246
bazaar/plugin/gdal/frmts/aigrid/aitest.c
Normal file
246
bazaar/plugin/gdal/frmts/aigrid/aitest.c
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
/******************************************************************************
|
||||
* $Id: aitest.c 28039 2014-11-30 18:24:59Z rouault $
|
||||
*
|
||||
* Project: Arc/Info Binary Grid Translator
|
||||
* Purpose: Test mainline for examining AIGrid files.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 1999, Frank Warmerdam
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "aigrid.h"
|
||||
|
||||
CPL_CVSID("$Id: aitest.c 28039 2014-11-30 18:24:59Z rouault $");
|
||||
|
||||
/************************************************************************/
|
||||
/* DumpMagic() */
|
||||
/* */
|
||||
/* Dump the magic ``block type byte'' for each existing block. */
|
||||
/************************************************************************/
|
||||
|
||||
static void DumpMagic( AIGInfo_t * psInfo, int bVerbose )
|
||||
|
||||
{
|
||||
int i;
|
||||
AIGTileInfo *psTInfo = psInfo->pasTileInfo + 0;
|
||||
|
||||
for( i = 0; i < psTInfo->nBlocks; i++ )
|
||||
{
|
||||
GByte byMagic;
|
||||
int bReport = bVerbose;
|
||||
unsigned char abyBlockSize[2];
|
||||
const char *pszMessage = "";
|
||||
|
||||
if( psTInfo->panBlockSize[i] == 0 )
|
||||
continue;
|
||||
|
||||
VSIFSeekL( psTInfo->fpGrid, psTInfo->panBlockOffset[i], SEEK_SET );
|
||||
VSIFReadL( abyBlockSize, 2, 1, psTInfo->fpGrid );
|
||||
|
||||
if( psInfo->nCellType == AIG_CELLTYPE_INT && psInfo->bCompressed )
|
||||
{
|
||||
VSIFReadL( &byMagic, 1, 1, psTInfo->fpGrid );
|
||||
|
||||
if( byMagic != 0 && byMagic != 0x43 && byMagic != 0x04
|
||||
&& byMagic != 0x08 && byMagic != 0x10 && byMagic != 0xd7
|
||||
&& byMagic != 0xdf && byMagic != 0xe0 && byMagic != 0xfc
|
||||
&& byMagic != 0xf8 && byMagic != 0xff && byMagic != 0x41
|
||||
&& byMagic != 0x40 && byMagic != 0x42 && byMagic != 0xf0
|
||||
&& byMagic != 0xcf && byMagic != 0x01 )
|
||||
{
|
||||
pszMessage = "(unhandled magic number)";
|
||||
bReport = TRUE;
|
||||
}
|
||||
|
||||
if( byMagic == 0 && psTInfo->panBlockSize[i] > 8 )
|
||||
{
|
||||
pszMessage = "(wrong size for 0x00 block, should be 8 bytes)";
|
||||
bReport = TRUE;
|
||||
}
|
||||
|
||||
if( (abyBlockSize[0] * 256 + abyBlockSize[1])*2 !=
|
||||
psTInfo->panBlockSize[i] )
|
||||
{
|
||||
pszMessage = "(block size in data doesn't match index)";
|
||||
bReport = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( psTInfo->panBlockSize[i] !=
|
||||
psInfo->nBlockXSize*psInfo->nBlockYSize*sizeof(float) )
|
||||
{
|
||||
pszMessage = "(floating point block size is wrong)";
|
||||
bReport = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if( bReport )
|
||||
{
|
||||
printf( " %02x %5d %5d @ %d %s\n", byMagic, i,
|
||||
psTInfo->panBlockSize[i],
|
||||
psTInfo->panBlockOffset[i],
|
||||
pszMessage );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* main() */
|
||||
/************************************************************************/
|
||||
|
||||
int main( int argc, char ** argv )
|
||||
|
||||
{
|
||||
AIGInfo_t *psInfo;
|
||||
GInt32 *panRaster;
|
||||
int i, j;
|
||||
int bMagic = FALSE, bSuppressMagic = FALSE;
|
||||
int iTestTileX = 0, iTestTileY = 0;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Process arguments. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
while( argc > 1 && argv[1][0] == '-' )
|
||||
{
|
||||
if( EQUAL(argv[1],"-magic") )
|
||||
bMagic = TRUE;
|
||||
|
||||
else if( EQUAL(argv[1],"-nomagic") )
|
||||
bSuppressMagic = TRUE;
|
||||
|
||||
else if( EQUAL(argv[1],"-t") && argc > 2 )
|
||||
{
|
||||
iTestTileX = atoi(argv[2]);
|
||||
iTestTileY = atoi(argv[3]);
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if( argc < 2 ) {
|
||||
printf( "Usage: aitest [-magic] coverage [block numbers...]\n" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Open dataset. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
psInfo = AIGOpen( argv[1], "r" );
|
||||
if( psInfo == NULL )
|
||||
exit( 1 );
|
||||
|
||||
AIGAccessTile( psInfo, iTestTileX, iTestTileY );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Dump general information */
|
||||
/* -------------------------------------------------------------------- */
|
||||
printf( "%d pixels x %d lines.\n", psInfo->nPixels, psInfo->nLines );
|
||||
printf( "Lower Left = (%f,%f) Upper Right = (%f,%f)\n",
|
||||
psInfo->dfLLX,
|
||||
psInfo->dfLLY,
|
||||
psInfo->dfURX,
|
||||
psInfo->dfURY );
|
||||
|
||||
if( psInfo->nCellType == AIG_CELLTYPE_INT )
|
||||
printf( "%s Integer coverage, %dx%d blocks.\n",
|
||||
psInfo->bCompressed ? "Compressed" : "Uncompressed",
|
||||
psInfo->nBlockXSize, psInfo->nBlockYSize );
|
||||
else
|
||||
printf( "%s Floating point coverage, %dx%d blocks.\n",
|
||||
psInfo->bCompressed ? "Compressed" : "Uncompressed",
|
||||
psInfo->nBlockXSize, psInfo->nBlockYSize );
|
||||
|
||||
printf( "Stats - Min=%f, Max=%f, Mean=%f, StdDev=%f\n",
|
||||
psInfo->dfMin,
|
||||
psInfo->dfMax,
|
||||
psInfo->dfMean,
|
||||
psInfo->dfStdDev );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Do we want a dump of all the ``magic'' numbers for */
|
||||
/* instantated blocks? */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( !bSuppressMagic )
|
||||
DumpMagic( psInfo, bMagic );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read a block, and report it's contents. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
panRaster = (GInt32 *)
|
||||
CPLMalloc(psInfo->nBlockXSize * psInfo->nBlockYSize * 4);
|
||||
|
||||
while( argc > 2 && (atoi(argv[2]) > 0 || argv[2][0] == '0') )
|
||||
{
|
||||
int nBlock = atoi(argv[2]);
|
||||
CPLErr eErr;
|
||||
AIGTileInfo *psTInfo = psInfo->pasTileInfo + 0;
|
||||
|
||||
argv++;
|
||||
argc--;
|
||||
|
||||
eErr = AIGReadBlock( psTInfo->fpGrid,
|
||||
psTInfo->panBlockOffset[nBlock],
|
||||
psTInfo->panBlockSize[nBlock],
|
||||
psInfo->nBlockXSize, psInfo->nBlockYSize,
|
||||
panRaster, psInfo->nCellType, psInfo->bCompressed);
|
||||
|
||||
printf( "\nBlock %d:\n", nBlock );
|
||||
|
||||
if( eErr != CE_None )
|
||||
{
|
||||
printf( " Error! Skipping block.\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
for( j = 0; j < psInfo->nBlockYSize; j++ )
|
||||
{
|
||||
for( i = 0; i < psInfo->nBlockXSize; i++ )
|
||||
{
|
||||
if( i > 18 )
|
||||
{
|
||||
printf( "..." );
|
||||
break;
|
||||
}
|
||||
|
||||
if( panRaster[i+j*psInfo->nBlockXSize] == ESRI_GRID_NO_DATA )
|
||||
printf( "-*- " );
|
||||
else if( psInfo->nCellType == AIG_CELLTYPE_FLOAT )
|
||||
printf( "%f ",
|
||||
((float *) panRaster)[i+j*psInfo->nBlockXSize] );
|
||||
else
|
||||
printf( "%3d ", panRaster[i+j*psInfo->nBlockXSize] );
|
||||
}
|
||||
printf( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
CPLFree( panRaster );
|
||||
|
||||
AIGClose( psInfo );
|
||||
|
||||
exit( 0 );
|
||||
}
|
||||
1097
bazaar/plugin/gdal/frmts/aigrid/gridlib.c
Normal file
1097
bazaar/plugin/gdal/frmts/aigrid/gridlib.c
Normal file
File diff suppressed because it is too large
Load diff
21
bazaar/plugin/gdal/frmts/aigrid/makefile.vc
Normal file
21
bazaar/plugin/gdal/frmts/aigrid/makefile.vc
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
OBJ = aigdataset.obj aigopen.obj gridlib.obj aigccitt.obj
|
||||
|
||||
EXTRAFLAGS = -I../../ogr/ogrsf_frmts/avc
|
||||
|
||||
GDAL_ROOT = ..\..
|
||||
|
||||
!INCLUDE $(GDAL_ROOT)\nmake.opt
|
||||
|
||||
default: $(OBJ)
|
||||
xcopy /D /Y *.obj ..\o
|
||||
|
||||
all: $(OBJ) aitest.exe
|
||||
|
||||
aitest.exe: $(OBJ) aitest.c
|
||||
$(CC) $(CFLAGS) aitest.c aigopen.obj gridlib.obj \
|
||||
$(GDAL_ROOT)/port/cpl.lib
|
||||
|
||||
clean:
|
||||
-del *.obj
|
||||
|
||||
13
bazaar/plugin/gdal/frmts/airsar/GNUmakefile
Normal file
13
bazaar/plugin/gdal/frmts/airsar/GNUmakefile
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
include ../../GDALmake.opt
|
||||
|
||||
OBJ = airsardataset.o
|
||||
|
||||
|
||||
|
||||
default: $(OBJ:.o=.$(OBJ_EXT))
|
||||
|
||||
clean:
|
||||
rm -f *.o $(O_OBJ)
|
||||
|
||||
install-obj: $(O_OBJ:.o=.$(OBJ_EXT))
|
||||
673
bazaar/plugin/gdal/frmts/airsar/airsardataset.cpp
Normal file
673
bazaar/plugin/gdal/frmts/airsar/airsardataset.cpp
Normal file
|
|
@ -0,0 +1,673 @@
|
|||
/******************************************************************************
|
||||
* $Id: airsardataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
|
||||
*
|
||||
* Project: AirSAR Reader
|
||||
* Purpose: Implements read support for AirSAR Polarimetric data.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
|
||||
* Copyright (c) 2007-2009, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gdal_pam.h"
|
||||
#include "cpl_string.h"
|
||||
#include "cpl_conv.h"
|
||||
#include "cpl_vsi.h"
|
||||
|
||||
CPL_CVSID("$Id: airsardataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
|
||||
|
||||
CPL_C_START
|
||||
void GDALRegister_AirSAR(void);
|
||||
CPL_C_END
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* AirSARDataset */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
class AirSARRasterBand;
|
||||
|
||||
class AirSARDataset : public GDALPamDataset
|
||||
{
|
||||
friend class AirSARRasterBand;
|
||||
|
||||
VSILFILE *fp;
|
||||
|
||||
int nLoadedLine;
|
||||
GByte *pabyCompressedLine;
|
||||
double *padfMatrix;
|
||||
|
||||
int nDataStart;
|
||||
int nRecordLength;
|
||||
|
||||
CPLErr LoadLine(int iLine);
|
||||
|
||||
static char **ReadHeader( VSILFILE * fp, int nFileOffset,
|
||||
const char *pszPrefix, int nMaxLines );
|
||||
|
||||
public:
|
||||
AirSARDataset();
|
||||
~AirSARDataset();
|
||||
|
||||
static GDALDataset *Open( GDALOpenInfo * );
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* AirSARRasterBand */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
class AirSARRasterBand : public GDALPamRasterBand
|
||||
{
|
||||
public:
|
||||
AirSARRasterBand( AirSARDataset *, int );
|
||||
virtual ~AirSARRasterBand();
|
||||
|
||||
virtual CPLErr IReadBlock( int, int, void * );
|
||||
};
|
||||
|
||||
/* locations of stokes matrix values within padfMatrix ... same order as they
|
||||
are computed in the document. */
|
||||
|
||||
#define M11 0
|
||||
#define M12 1
|
||||
#define M13 2
|
||||
#define M14 3
|
||||
#define M23 4
|
||||
#define M24 5
|
||||
#define M33 6
|
||||
#define M34 7
|
||||
#define M44 8
|
||||
#define M22 9
|
||||
|
||||
/************************************************************************/
|
||||
/* AirSARRasterBand() */
|
||||
/************************************************************************/
|
||||
|
||||
AirSARRasterBand::AirSARRasterBand( AirSARDataset *poDS,
|
||||
int nBand )
|
||||
|
||||
{
|
||||
this->poDS = poDS;
|
||||
this->nBand = nBand;
|
||||
|
||||
nBlockXSize = poDS->GetRasterXSize();
|
||||
nBlockYSize = 1;
|
||||
|
||||
if( this->nBand == 2 || this->nBand == 3 || this->nBand == 5 )
|
||||
eDataType = GDT_CFloat32;
|
||||
else
|
||||
eDataType = GDT_Float32;
|
||||
|
||||
switch( nBand )
|
||||
{
|
||||
case 1:
|
||||
SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_11" );
|
||||
SetDescription( "Covariance_11" );
|
||||
eDataType = GDT_CFloat32;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_12" );
|
||||
SetDescription( "Covariance_12" );
|
||||
eDataType = GDT_CFloat32;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_13" );
|
||||
SetDescription( "Covariance_13" );
|
||||
eDataType = GDT_CFloat32;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_22" );
|
||||
SetDescription( "Covariance_22" );
|
||||
eDataType = GDT_CFloat32;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_23" );
|
||||
SetDescription( "Covariance_23" );
|
||||
eDataType = GDT_CFloat32;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_33" );
|
||||
SetDescription( "Covariance_33" );
|
||||
eDataType = GDT_CFloat32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ~AirSARRasterBand() */
|
||||
/************************************************************************/
|
||||
|
||||
AirSARRasterBand::~AirSARRasterBand()
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* IReadBlock() */
|
||||
/************************************************************************/
|
||||
|
||||
CPLErr AirSARRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
|
||||
int nBlockYOff,
|
||||
void * pImage )
|
||||
{
|
||||
CPLErr eErr;
|
||||
float *pafLine = (float *) pImage;
|
||||
int iPixel;
|
||||
double *padfMatrix;
|
||||
|
||||
eErr = ((AirSARDataset *)poDS)->LoadLine( nBlockYOff );
|
||||
if( eErr != CE_None )
|
||||
return eErr;
|
||||
|
||||
padfMatrix = ((AirSARDataset *) poDS)->padfMatrix;
|
||||
|
||||
#define SQRT_2 1.4142135623730951
|
||||
|
||||
if( nBand == 1 ) /* C11 */
|
||||
{
|
||||
for( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
|
||||
{
|
||||
double *m = padfMatrix + 10 * iPixel;
|
||||
|
||||
pafLine[iPixel*2+0] = (float)(m[M11] + m[M22] + 2 * m[M12]);
|
||||
pafLine[iPixel*2+1] = 0.0;
|
||||
}
|
||||
}
|
||||
else if( nBand == 2 ) /* C12 */
|
||||
{
|
||||
for( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
|
||||
{
|
||||
double *m = padfMatrix + 10 * iPixel;
|
||||
|
||||
// real
|
||||
pafLine[iPixel*2 + 0] = (float)(SQRT_2 * (m[M13] + m[M23]));
|
||||
|
||||
// imaginary
|
||||
pafLine[iPixel*2 + 1] = (float)(- SQRT_2 * (m[M24] + m[M14]));
|
||||
}
|
||||
}
|
||||
else if( nBand == 3 ) /* C13 */
|
||||
{
|
||||
for( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
|
||||
{
|
||||
double *m = padfMatrix + 10 * iPixel;
|
||||
|
||||
// real
|
||||
pafLine[iPixel*2 + 0] = (float)(2*m[M33] + m[M22] - m[M11]);
|
||||
|
||||
// imaginary
|
||||
pafLine[iPixel*2 + 1] = (float)(-2 * m[M34]);
|
||||
}
|
||||
}
|
||||
else if( nBand == 4 ) /* C22 */
|
||||
{
|
||||
for( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
|
||||
{
|
||||
double *m = padfMatrix + 10 * iPixel;
|
||||
|
||||
pafLine[iPixel*2+0] = (float)(2 * (m[M11] - m[M22]));
|
||||
pafLine[iPixel*2+1] = 0.0;
|
||||
}
|
||||
}
|
||||
else if( nBand == 5 ) /* C23 */
|
||||
{
|
||||
for( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
|
||||
{
|
||||
double *m = padfMatrix + 10 * iPixel;
|
||||
|
||||
// real
|
||||
pafLine[iPixel*2 + 0] = (float)(SQRT_2 * (m[M13] - m[M23]));
|
||||
|
||||
// imaginary
|
||||
pafLine[iPixel*2 + 1] = (float)(SQRT_2 * (m[M23] - m[M14]));
|
||||
}
|
||||
}
|
||||
else if( nBand == 6 ) /* C33 */
|
||||
{
|
||||
for( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
|
||||
{
|
||||
double *m = padfMatrix + 10 * iPixel;
|
||||
|
||||
pafLine[iPixel*2+0] = (float)(m[M11] + m[M22] - 2 * m[M12]);
|
||||
pafLine[iPixel*2+1] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* AirSARDataset */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
/************************************************************************/
|
||||
/* AirSARDataset() */
|
||||
/************************************************************************/
|
||||
|
||||
AirSARDataset::AirSARDataset()
|
||||
|
||||
{
|
||||
fp = NULL;
|
||||
|
||||
nLoadedLine = -1;
|
||||
pabyCompressedLine = NULL;
|
||||
padfMatrix = NULL;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ~AirSARDataset() */
|
||||
/************************************************************************/
|
||||
|
||||
AirSARDataset::~AirSARDataset()
|
||||
|
||||
{
|
||||
FlushCache();
|
||||
if( pabyCompressedLine != NULL )
|
||||
{
|
||||
CPLFree( pabyCompressedLine );
|
||||
CPLFree( padfMatrix );
|
||||
}
|
||||
|
||||
if( fp != NULL )
|
||||
{
|
||||
VSIFCloseL( fp );
|
||||
fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* LoadLine() */
|
||||
/************************************************************************/
|
||||
|
||||
CPLErr AirSARDataset::LoadLine( int iLine )
|
||||
|
||||
{
|
||||
if( iLine == nLoadedLine )
|
||||
return CE_None;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* allocate working buffers if we don't have them already. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( pabyCompressedLine == NULL )
|
||||
{
|
||||
pabyCompressedLine = (GByte *) VSIMalloc2(nRasterXSize, 10);
|
||||
|
||||
padfMatrix = (double *) VSIMalloc2(10* sizeof(double), nRasterXSize);
|
||||
if (pabyCompressedLine == NULL ||
|
||||
padfMatrix == NULL)
|
||||
{
|
||||
CPLError(CE_Failure, CPLE_OutOfMemory,
|
||||
"AirSARDataset::LoadLine : Out of memory. "
|
||||
"Probably due to corrupted dataset (nRasterXSize = %d)",
|
||||
nRasterXSize);
|
||||
CPLFree (pabyCompressedLine);
|
||||
CPLFree (padfMatrix);
|
||||
return CE_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
CPLAssert( nRecordLength == nRasterXSize * 10 );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Load raw compressed data. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( VSIFSeekL( fp, nDataStart + iLine * nRecordLength, SEEK_SET ) != 0
|
||||
|| ((int) VSIFReadL( pabyCompressedLine, 10, nRasterXSize, fp ))
|
||||
!= nRasterXSize )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_FileIO,
|
||||
"Error reading %d bytes for line %d at offset %d.\n%s",
|
||||
nRasterXSize * 10, iLine, nDataStart + iLine * nRecordLength,
|
||||
VSIStrerror( errno ) );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Build stokes matrix */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
|
||||
{
|
||||
double *M = padfMatrix + 10 * iPixel;
|
||||
signed char *byte = (signed char *) pabyCompressedLine + 10*iPixel - 1;
|
||||
double gen_fac = 1.0; // should we have a general scale factor?
|
||||
|
||||
M[M11] = (byte[2] / 254.0 + 1.5) * pow(2.0,byte[1]) * gen_fac;
|
||||
M[M12] = byte[3] * M[M11] / 127.0;
|
||||
M[M13] = byte[4] * fabs((double) byte[4]) * M[M11] / (127*127);
|
||||
M[M14] = byte[5] * fabs((double) byte[5]) * M[M11] / (127*127);
|
||||
M[M23] = byte[6] * fabs((double) byte[6]) * M[M11] / (127*127);
|
||||
M[M24] = byte[7] * fabs((double) byte[7]) * M[M11] / (127*127);
|
||||
M[M33] = byte[8] * M[M11] / 127;
|
||||
M[M34] = byte[9] * M[M11] / 127;
|
||||
M[M44] = byte[10] * M[M11] / 127;
|
||||
M[M22] = M[M11] - M[M33] - M[M44];
|
||||
}
|
||||
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ReadHeader() */
|
||||
/* */
|
||||
/* Read the AirSAR header. We assume an equal sign seperates */
|
||||
/* the keyword name from the value. If not, assume the last */
|
||||
/* "blank delimited" word is the value and everything else is a */
|
||||
/* keyword. */
|
||||
/* */
|
||||
/* The records are 50 characters each. Read till we get an all */
|
||||
/* blank record or some zero bytes. */
|
||||
/************************************************************************/
|
||||
|
||||
char ** AirSARDataset::ReadHeader( VSILFILE * fp, int nFileOffset,
|
||||
const char *pszPrefix, int nMaxLines )
|
||||
|
||||
{
|
||||
char **papszHeadInfo = NULL;
|
||||
char szLine[51];
|
||||
int iLine;
|
||||
|
||||
VSIFSeekL( fp, nFileOffset, SEEK_SET );
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Loop collecting one line at a time. */
|
||||
/* ==================================================================== */
|
||||
for( iLine = 0; iLine < nMaxLines; iLine++ )
|
||||
{
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read a 50 byte header record. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( VSIFReadL( szLine, 1, 50, fp ) != 50 )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_FileIO,
|
||||
"Read error collecting AirSAR header." );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
szLine[50] = '\0';
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Is it all spaces, or does it have a zero byte? */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int bAllSpaces = TRUE;
|
||||
int bHasIllegalChars = FALSE;
|
||||
int i;
|
||||
|
||||
for( i = 0; i < 50; i++ )
|
||||
{
|
||||
if( szLine[i] == '\0' )
|
||||
break;
|
||||
|
||||
if( szLine[i] != ' ' )
|
||||
bAllSpaces = FALSE;
|
||||
|
||||
if( ((unsigned char *) szLine)[i] > 127
|
||||
|| ((unsigned char *) szLine)[i] < 10 )
|
||||
bHasIllegalChars = TRUE;
|
||||
}
|
||||
|
||||
if( bAllSpaces || bHasIllegalChars )
|
||||
break;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Find the pivot between the keyword name and value. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int iPivot = -1;
|
||||
|
||||
for( i = 0; i < 50; i++ )
|
||||
{
|
||||
if( szLine[i] == '=' )
|
||||
{
|
||||
iPivot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no "=" found, split on first double white space
|
||||
if( iPivot == -1 )
|
||||
{
|
||||
for( i = 48; i >= 0; i-- )
|
||||
{
|
||||
if( szLine[i] == ' ' && szLine[i+1] == ' ' )
|
||||
{
|
||||
iPivot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( iPivot == -1 ) // Yikes!
|
||||
{
|
||||
CPLDebug( "AIRSAR", "No pivot in line `%s'.",
|
||||
szLine );
|
||||
CPLAssert( iPivot != -1 );
|
||||
break;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Trace ahead to the first non-white space value character. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int iValue = iPivot + 1;
|
||||
|
||||
while( iValue < 50 && szLine[iValue] == ' ' )
|
||||
iValue++;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Strip any white space off the keyword. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int iKeyEnd = iPivot - 1;
|
||||
|
||||
while( iKeyEnd > 0 && szLine[iKeyEnd] == ' ' )
|
||||
iKeyEnd--;
|
||||
|
||||
szLine[iKeyEnd+1] = '\0';
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Convert spaces or colons into underscores in the key name. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( i = 0; szLine[i] != '\0'; i++ )
|
||||
{
|
||||
if( szLine[i] == ' ' || szLine[i] == ':' || szLine[i] == ',' )
|
||||
szLine[i] = '_';
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Prefix key name with provided prefix string. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
char szPrefixedKeyName[55];
|
||||
|
||||
sprintf( szPrefixedKeyName, "%s_%s", pszPrefix, szLine );
|
||||
|
||||
papszHeadInfo =
|
||||
CSLSetNameValue( papszHeadInfo, szPrefixedKeyName, szLine+iValue );
|
||||
|
||||
}
|
||||
|
||||
return papszHeadInfo;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Open() */
|
||||
/************************************************************************/
|
||||
|
||||
GDALDataset *AirSARDataset::Open( GDALOpenInfo * poOpenInfo )
|
||||
|
||||
{
|
||||
if( poOpenInfo->fpL == NULL || poOpenInfo->nHeaderBytes < 800 )
|
||||
return NULL;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Check for AirSAR/ keyword. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( !EQUALN((char *) poOpenInfo->pabyHeader, "RECORD LENGTH IN BYTES",22) )
|
||||
return NULL;
|
||||
|
||||
if( strstr((char *) poOpenInfo->pabyHeader, "COMPRESSED") == NULL
|
||||
|| strstr((char *) poOpenInfo->pabyHeader, "JPL AIRCRAFT") == NULL )
|
||||
return NULL;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Parse the header fields. We turn all the transform the */
|
||||
/* keywords by converting spaces to underscores so they will be */
|
||||
/* "well behaved" as metadata keywords. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
char **papszMD = ReadHeader( poOpenInfo->fpL, 0, "MH", 20 );
|
||||
|
||||
if( papszMD == NULL )
|
||||
return NULL;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Confirm the requested access is supported. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( poOpenInfo->eAccess == GA_Update )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_NotSupported,
|
||||
"The AIRSAR driver does not support update access to existing"
|
||||
" datasets.\n" );
|
||||
return NULL;
|
||||
}
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create a corresponding GDALDataset. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
AirSARDataset *poDS;
|
||||
|
||||
poDS = new AirSARDataset();
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Extract some key information. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
poDS->nRasterXSize =
|
||||
atoi(CSLFetchNameValue(papszMD,"MH_NUMBER_OF_SAMPLES_PER_RECORD"));
|
||||
poDS->nRasterYSize =
|
||||
atoi(CSLFetchNameValue(papszMD,"MH_NUMBER_OF_LINES_IN_IMAGE"));
|
||||
|
||||
poDS->nRecordLength = atoi(
|
||||
CSLFetchNameValue( papszMD, "MH_RECORD_LENGTH_IN_BYTES" ) );
|
||||
|
||||
poDS->nDataStart = atoi(
|
||||
CSLFetchNameValue( papszMD, "MH_BYTE_OFFSET_OF_FIRST_DATA_RECORD" ));
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Adopt the openinfo file pointer. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poDS->fp = poOpenInfo->fpL;
|
||||
poOpenInfo->fpL = NULL;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read and merge parameter header into metadata. Prefix */
|
||||
/* parameter header values with PH_. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int nPHOffset = 0;
|
||||
|
||||
if( CSLFetchNameValue( papszMD,
|
||||
"MH_BYTE_OFFSET_OF_PARAMETER_HEADER" ) != NULL )
|
||||
{
|
||||
nPHOffset = atoi(CSLFetchNameValue(
|
||||
papszMD, "MH_BYTE_OFFSET_OF_PARAMETER_HEADER"));
|
||||
char **papszPHInfo = ReadHeader( poDS->fp, nPHOffset, "PH", 100 );
|
||||
|
||||
papszMD = CSLInsertStrings( papszMD, CSLCount(papszMD), papszPHInfo );
|
||||
|
||||
CSLDestroy( papszPHInfo );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read and merge calibration header into metadata. Prefix */
|
||||
/* parameter header values with CH_. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( nPHOffset != 0 )
|
||||
{
|
||||
char **papszCHInfo = ReadHeader( poDS->fp,
|
||||
nPHOffset+poDS->nRecordLength,
|
||||
"CH", 18 );
|
||||
|
||||
papszMD = CSLInsertStrings( papszMD, CSLCount(papszMD), papszCHInfo );
|
||||
|
||||
CSLDestroy( papszCHInfo );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Assign metadata to dataset. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poDS->SetMetadata( papszMD );
|
||||
CSLDestroy( papszMD );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create band information objects. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poDS->SetBand( 1, new AirSARRasterBand( poDS, 1 ));
|
||||
poDS->SetBand( 2, new AirSARRasterBand( poDS, 2 ));
|
||||
poDS->SetBand( 3, new AirSARRasterBand( poDS, 3 ));
|
||||
poDS->SetBand( 4, new AirSARRasterBand( poDS, 4 ));
|
||||
poDS->SetBand( 5, new AirSARRasterBand( poDS, 5 ));
|
||||
poDS->SetBand( 6, new AirSARRasterBand( poDS, 6 ));
|
||||
|
||||
poDS->SetMetadataItem( "MATRIX_REPRESENTATION", "SYMMETRIZED_COVARIANCE" );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Initialize any PAM information. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poDS->SetDescription( poOpenInfo->pszFilename );
|
||||
poDS->TryLoadXML();
|
||||
|
||||
poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
|
||||
|
||||
return( poDS );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALRegister_AirSAR() */
|
||||
/************************************************************************/
|
||||
|
||||
void GDALRegister_AirSAR()
|
||||
|
||||
{
|
||||
GDALDriver *poDriver;
|
||||
|
||||
if( GDALGetDriverByName( "AirSAR" ) == NULL )
|
||||
{
|
||||
poDriver = new GDALDriver();
|
||||
|
||||
poDriver->SetDescription( "AirSAR" );
|
||||
poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
|
||||
poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
|
||||
"AirSAR Polarimetric Image" );
|
||||
poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_airsar.html" );
|
||||
|
||||
poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
|
||||
|
||||
poDriver->pfnOpen = AirSARDataset::Open;
|
||||
|
||||
GetGDALDriverManager()->RegisterDriver( poDriver );
|
||||
}
|
||||
}
|
||||
57
bazaar/plugin/gdal/frmts/airsar/frmt_airsar.html
Normal file
57
bazaar/plugin/gdal/frmts/airsar/frmt_airsar.html
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>AIRSAR -- AIRSAR Polarimetric Format</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff">
|
||||
|
||||
<h1>AIRSAR -- AIRSAR Polarimetric Format</h1>
|
||||
|
||||
Most variants of the AIRSAR Polarimetric Format produced by the AIRSAR
|
||||
Integrated Processor are supported for reading by GDAL. AIRSAR products
|
||||
normally include various associated data files, but only the imagery
|
||||
data themselves is supported. Normally these are named <i>mission</i>_l.dat
|
||||
(L-Band) or <i>mission</i>_c.dat (C-Band).<p>
|
||||
|
||||
AIRSAR format contains a polarimetric image in compressed stokes matrix form.
|
||||
Internally GDAL decompresses the data into a stokes matrix, and then converts
|
||||
that form into a covariance matrix. The returned six bands are the six values
|
||||
needed to define the 3x3 Hermitian covariance matrix. The convention used
|
||||
to represent the covariance matrix in terms of the scattering matrix
|
||||
elements HH, HV (=VH), and VV is indicated below. Note that the
|
||||
non-diagonal elements of the matrix are complex values, while the diagonal
|
||||
values are real (though represented as complex bands).<p>
|
||||
|
||||
<ul>
|
||||
<li> Band 1: Covariance_11 (Float32) = HH*conj(HH)
|
||||
<li> Band 2: Covariance_12 (CFloat32) = sqrt(2)*HH*conj(HV)
|
||||
<li> Band 3: Covariance_13 (CFloat32) = HH*conj(VV)
|
||||
<li> Band 4: Covariance_22 (Float32) = 2*HV*conj(HV)
|
||||
<li> Band 5: Covariance_23 (CFloat32) = sqrt(2)*HV*conj(VV)
|
||||
<li> Band 6: Covariance_33 (Float32) = VV*conj(VV)
|
||||
</ul>
|
||||
|
||||
|
||||
The identities of the bands are also reflected in metadata and in the band
|
||||
descriptions. <p>
|
||||
|
||||
The AIRSAR product format includes (potentially) several headers of
|
||||
information. This information is captured and represented as metadata on the
|
||||
file as a whole. Information items from the main header are prefixed with
|
||||
"MH_", items from the parameter header are prefixed with "PH_" and
|
||||
information from the calibration header are prefixed with "CH_".
|
||||
The metadata item names are derived automatically from the names of the
|
||||
fields within the header itself. <p>
|
||||
|
||||
No effort is made to read files associated with the AIRSAR product such as
|
||||
<i>mission</i>_l.mocomp, <i>mission</i>_meta.airsar or
|
||||
<i>mission</i>_meta.podaac.<p>
|
||||
|
||||
See Also:<p>
|
||||
|
||||
<ul>
|
||||
<li> <a href="http://airsar.jpl.nasa.gov/documents/dataformat.htm">AIRSAR Data Format</a>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
13
bazaar/plugin/gdal/frmts/airsar/makefile.vc
Normal file
13
bazaar/plugin/gdal/frmts/airsar/makefile.vc
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
OBJ = airsardataset.obj
|
||||
|
||||
GDAL_ROOT = ..\..
|
||||
|
||||
!INCLUDE $(GDAL_ROOT)\nmake.opt
|
||||
|
||||
default: $(OBJ)
|
||||
xcopy /D /Y *.obj ..\o
|
||||
|
||||
clean:
|
||||
-del *.obj
|
||||
|
||||
14
bazaar/plugin/gdal/frmts/arg/GNUmakefile
Normal file
14
bazaar/plugin/gdal/frmts/arg/GNUmakefile
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
|
||||
include ../../GDALmake.opt
|
||||
|
||||
OBJ = argdataset.o
|
||||
|
||||
CPPFLAGS := $(JSON_INCLUDE) -I../raw $(CPPFLAGS)
|
||||
|
||||
default: $(OBJ:.o=.$(OBJ_EXT))
|
||||
|
||||
clean:
|
||||
rm -f *.o $(O_OBJ)
|
||||
|
||||
install-obj: $(O_OBJ:.o=.$(OBJ_EXT))
|
||||
850
bazaar/plugin/gdal/frmts/arg/argdataset.cpp
Normal file
850
bazaar/plugin/gdal/frmts/arg/argdataset.cpp
Normal file
|
|
@ -0,0 +1,850 @@
|
|||
/******************************************************************************
|
||||
* $Id: argdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
|
||||
*
|
||||
* Project: Azavea Raster Grid format driver.
|
||||
* Purpose: Implements support for reading and writing Azavea Raster Grid
|
||||
* format.
|
||||
* Author: David Zwarg <dzwarg@azavea.com>
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2012, David Zwarg <dzwarg@azavea.com>
|
||||
* Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "rawdataset.h"
|
||||
#include "cpl_string.h"
|
||||
#include <json.h>
|
||||
#include <ogr_spatialref.h>
|
||||
|
||||
CPL_CVSID("$Id: argdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
|
||||
|
||||
#define MAX_FILENAME_LEN 4096
|
||||
|
||||
#ifndef NAN
|
||||
# ifdef HUGE_VAL
|
||||
# define NAN (HUGE_VAL * 0.0)
|
||||
# else
|
||||
|
||||
static float CPLNaN(void)
|
||||
{
|
||||
float fNan;
|
||||
int nNan = 0x7FC00000;
|
||||
memcpy(&fNan, &nNan, 4);
|
||||
return fNan;
|
||||
}
|
||||
|
||||
# define NAN CPLNaN()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* ARGDataset */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
class ARGDataset : public RawDataset
|
||||
{
|
||||
VSILFILE *fpImage; // image data file.
|
||||
|
||||
double adfGeoTransform[6];
|
||||
char * pszFilename;
|
||||
|
||||
public:
|
||||
ARGDataset();
|
||||
~ARGDataset();
|
||||
|
||||
CPLErr GetGeoTransform( double * padfTransform );
|
||||
|
||||
static int Identify( GDALOpenInfo * );
|
||||
static GDALDataset *Open( GDALOpenInfo * );
|
||||
static GDALDataset *CreateCopy( const char *, GDALDataset *, int,
|
||||
char **, GDALProgressFunc, void *);
|
||||
virtual char ** GetFileList(void);
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* ARGDataset() */
|
||||
/************************************************************************/
|
||||
|
||||
ARGDataset::ARGDataset()
|
||||
{
|
||||
adfGeoTransform[0] = 0.0;
|
||||
adfGeoTransform[1] = 1.0;
|
||||
adfGeoTransform[2] = 0.0;
|
||||
adfGeoTransform[3] = 0.0;
|
||||
adfGeoTransform[4] = 0.0;
|
||||
adfGeoTransform[5] = 1.0;
|
||||
fpImage = NULL;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ~ARGDataset() */
|
||||
/************************************************************************/
|
||||
|
||||
ARGDataset::~ARGDataset()
|
||||
|
||||
{
|
||||
CPLFree(pszFilename);
|
||||
|
||||
FlushCache();
|
||||
if( fpImage != NULL )
|
||||
VSIFCloseL( fpImage );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GetGeoTransform() */
|
||||
/************************************************************************/
|
||||
|
||||
CPLErr ARGDataset::GetGeoTransform( double * padfTransform )
|
||||
|
||||
{
|
||||
memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
|
||||
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GetJsonFilename() */
|
||||
/************************************************************************/
|
||||
CPLString GetJsonFilename(CPLString pszFilename)
|
||||
{
|
||||
return CPLSPrintf( "%s/%s.json", CPLGetDirname(pszFilename), CPLGetBasename(pszFilename) );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GetJsonObject() */
|
||||
/************************************************************************/
|
||||
json_object * GetJsonObject(CPLString pszFilename)
|
||||
{
|
||||
json_object * pJSONObject = NULL;
|
||||
CPLString osJSONFilename = GetJsonFilename(pszFilename);
|
||||
|
||||
pJSONObject = json_object_from_file((char *)osJSONFilename.c_str());
|
||||
if (pJSONObject == NULL) {
|
||||
CPLDebug("ARGDataset", "GetJsonObject(): "
|
||||
"Could not parse JSON file.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pJSONObject;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GetJsonValueStr() */
|
||||
/************************************************************************/
|
||||
const char * GetJsonValueStr(json_object * pJSONObject, CPLString pszKey)
|
||||
{
|
||||
json_object * pJSONItem = json_object_object_get(pJSONObject, pszKey.c_str());
|
||||
if (pJSONItem == NULL) {
|
||||
CPLDebug("ARGDataset", "GetJsonValueStr(): "
|
||||
"Could not find '%s' in JSON.", pszKey.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return json_object_get_string(pJSONItem);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GetJsonValueDbl() */
|
||||
/************************************************************************/
|
||||
double GetJsonValueDbl(json_object * pJSONObject, CPLString pszKey)
|
||||
{
|
||||
const char *pszJSONStr = GetJsonValueStr(pJSONObject, pszKey.c_str());
|
||||
char *pszTmp;
|
||||
double fTmp;
|
||||
if (pszJSONStr == NULL) {
|
||||
return NAN;
|
||||
}
|
||||
pszTmp = (char *)pszJSONStr;
|
||||
fTmp = CPLStrtod(pszJSONStr, &pszTmp);
|
||||
if (pszTmp == pszJSONStr) {
|
||||
CPLDebug("ARGDataset", "GetJsonValueDbl(): "
|
||||
"Key value is not a numeric value: %s:%s", pszKey.c_str(), pszTmp);
|
||||
return NAN;
|
||||
}
|
||||
|
||||
return fTmp;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GetJsonValueInt() */
|
||||
/************************************************************************/
|
||||
int GetJsonValueInt(json_object * pJSONObject, CPLString pszKey)
|
||||
{
|
||||
double fTmp = GetJsonValueDbl(pJSONObject, pszKey.c_str());
|
||||
if (CPLIsNan(fTmp)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)fTmp;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GetFileList() */
|
||||
/************************************************************************/
|
||||
char ** ARGDataset::GetFileList()
|
||||
{
|
||||
char **papszFileList = GDALPamDataset::GetFileList();
|
||||
CPLString osJSONFilename = GetJsonFilename(pszFilename);
|
||||
|
||||
papszFileList = CSLAddString( papszFileList, osJSONFilename );
|
||||
|
||||
return papszFileList;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Identify() */
|
||||
/************************************************************************/
|
||||
|
||||
int ARGDataset::Identify( GDALOpenInfo *poOpenInfo )
|
||||
{
|
||||
json_object * pJSONObject;
|
||||
if (!EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "arg")) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pJSONObject = GetJsonObject(poOpenInfo->pszFilename);
|
||||
if (pJSONObject == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Open() */
|
||||
/************************************************************************/
|
||||
GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
|
||||
{
|
||||
json_object * pJSONObject;
|
||||
const char * pszJSONStr;
|
||||
char * pszLayer;
|
||||
/***** items from the json metadata *****/
|
||||
GDALDataType eType = GDT_Unknown;
|
||||
double fXmin = 0.0;
|
||||
double fYmin = 0.0;
|
||||
double fXmax = 0.0;
|
||||
double fYmax = 0.0;
|
||||
double fCellwidth = 1.0;
|
||||
double fCellheight = 1.0;
|
||||
double fXSkew = 0.0;
|
||||
double fYSkew = 0.0;
|
||||
int nRows = 0;
|
||||
int nCols = 0;
|
||||
int nSrs = 3857;
|
||||
/***** items from the json metadata *****/
|
||||
int nPixelOffset = 0;
|
||||
double fNoDataValue = NAN;
|
||||
|
||||
char * pszWKT = NULL;
|
||||
OGRSpatialReference oSRS;
|
||||
OGRErr nErr = OGRERR_NONE;
|
||||
|
||||
if ( !Identify( poOpenInfo ) )
|
||||
return NULL;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Check metadata settings in JSON. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
pJSONObject = GetJsonObject(poOpenInfo->pszFilename);
|
||||
|
||||
if (pJSONObject == NULL) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined, "Error parsing JSON.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the type (always 'arg')
|
||||
pszJSONStr = GetJsonValueStr(pJSONObject, "type");
|
||||
if (pszJSONStr == NULL ) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The ARG 'type' is missing from the JSON file.");
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
return NULL;
|
||||
}
|
||||
else if (!EQUAL(pszJSONStr, "arg")) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The ARG 'type' is not recognized: '%s'.", pszJSONStr);
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the datatype
|
||||
pszJSONStr = GetJsonValueStr(pJSONObject, "datatype");
|
||||
if (pszJSONStr == NULL) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The ARG 'datatype' is missing from the JSON file.");
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
return NULL;
|
||||
}
|
||||
else if (EQUAL(pszJSONStr, "int8")) {
|
||||
CPLDebug("ARGDataset", "Open(): "
|
||||
"int8 data is not supported in GDAL -- mapped to uint8");
|
||||
eType = GDT_Byte;
|
||||
nPixelOffset = 1;
|
||||
fNoDataValue = 128;
|
||||
}
|
||||
else if (EQUAL(pszJSONStr, "int16")) {
|
||||
eType = GDT_Int16;
|
||||
nPixelOffset = 2;
|
||||
fNoDataValue = -32767;
|
||||
}
|
||||
else if (EQUAL(pszJSONStr, "int32")) {
|
||||
eType = GDT_Int32;
|
||||
nPixelOffset = 4;
|
||||
fNoDataValue = -2e31;
|
||||
}
|
||||
else if (EQUAL(pszJSONStr, "uint8")) {
|
||||
eType = GDT_Byte;
|
||||
nPixelOffset = 1;
|
||||
fNoDataValue = 255;
|
||||
}
|
||||
else if (EQUAL(pszJSONStr, "uint16")) {
|
||||
eType = GDT_UInt16;
|
||||
nPixelOffset = 2;
|
||||
fNoDataValue = 65535;
|
||||
}
|
||||
else if (EQUAL(pszJSONStr, "uint32")) {
|
||||
eType = GDT_UInt32;
|
||||
nPixelOffset = 4;
|
||||
fNoDataValue = -2e31;
|
||||
}
|
||||
else if (EQUAL(pszJSONStr, "float32")) {
|
||||
eType = GDT_Float32;
|
||||
nPixelOffset = 4;
|
||||
fNoDataValue = NAN;
|
||||
}
|
||||
else if (EQUAL(pszJSONStr, "float64")) {
|
||||
eType = GDT_Float64;
|
||||
nPixelOffset = 8;
|
||||
fNoDataValue = NAN;
|
||||
}
|
||||
else {
|
||||
if (EQUAL(pszJSONStr, "int64") ||
|
||||
EQUAL(pszJSONStr, "uint64")) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The ARG 'datatype' is unsupported in GDAL: '%s'.", pszJSONStr);
|
||||
}
|
||||
else {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The ARG 'datatype' is unknown: '%s'.", pszJSONStr);
|
||||
}
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the xmin of the bounding box
|
||||
fXmin = GetJsonValueDbl(pJSONObject, "xmin");
|
||||
if (CPLIsNan(fXmin)) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The ARG 'xmin' is missing or invalid.");
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the ymin of the bounding box
|
||||
fYmin = GetJsonValueDbl(pJSONObject, "ymin");
|
||||
if (CPLIsNan(fYmin)) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The ARG 'ymin' is missing or invalid.");
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the xmax of the bounding box
|
||||
fXmax = GetJsonValueDbl(pJSONObject, "xmax");
|
||||
if (CPLIsNan(fXmax)) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The ARG 'xmax' is missing or invalid.");
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the ymax of the bounding box
|
||||
fYmax = GetJsonValueDbl(pJSONObject, "ymax");
|
||||
if (CPLIsNan(fYmax)) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The ARG 'ymax' is missing or invalid.");
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the cell width
|
||||
fCellwidth = GetJsonValueDbl(pJSONObject, "cellwidth");
|
||||
if (CPLIsNan(fCellwidth)) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The ARG 'cellwidth' is missing or invalid.");
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the cell height
|
||||
fCellheight = GetJsonValueDbl(pJSONObject, "cellheight");
|
||||
if (CPLIsNan(fCellheight)) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The ARG 'cellheight' is missing or invalid.");
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fXSkew = GetJsonValueDbl(pJSONObject, "xskew");
|
||||
if (CPLIsNan(fXSkew)) {
|
||||
// not an error -- default to 0.0
|
||||
fXSkew = 0.0f;
|
||||
}
|
||||
|
||||
fYSkew = GetJsonValueDbl(pJSONObject, "yskew");
|
||||
if (CPLIsNan(fYSkew)) {
|
||||
// not an error -- default to 0.0
|
||||
fYSkew = 0.0f;
|
||||
}
|
||||
|
||||
// get the rows
|
||||
nRows = GetJsonValueInt(pJSONObject, "rows");
|
||||
if (nRows < 0) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The ARG 'rows' is missing or invalid.");
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the columns
|
||||
nCols = GetJsonValueInt(pJSONObject, "cols");
|
||||
if (nCols < 0) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The ARG 'cols' is missing or invalid.");
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nSrs = GetJsonValueInt(pJSONObject, "epsg");
|
||||
if (nSrs < 0) {
|
||||
// not an error -- default to web mercator
|
||||
nSrs = 3857;
|
||||
}
|
||||
|
||||
nErr = oSRS.importFromEPSG(nSrs);
|
||||
if (nErr != OGRERR_NONE) {
|
||||
nErr = oSRS.importFromEPSG(3857);
|
||||
|
||||
if (nErr == OGRERR_NONE) {
|
||||
CPLDebug("ARGDataset", "Open(): "
|
||||
"The EPSG provided did not import cleanly. Defaulting to EPSG:3857");
|
||||
}
|
||||
else {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The 'epsg' value did not transate to a known spatial reference."
|
||||
" Please check the 'epsg' value and try again.");
|
||||
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
nErr = oSRS.exportToWkt(&pszWKT);
|
||||
if (nErr != OGRERR_NONE) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The spatial reference is known, but could not be set on the "
|
||||
"dataset. Please check the 'epsg' value and try again.");
|
||||
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the layer (always the file basename)
|
||||
pszJSONStr = GetJsonValueStr(pJSONObject, "layer");
|
||||
if (pszJSONStr == NULL) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"The ARG 'layer' is missing from the JSON file.");
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pszLayer = CPLStrdup(pszJSONStr);
|
||||
|
||||
// done with the json object now
|
||||
json_object_put(pJSONObject);
|
||||
pJSONObject = NULL;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create a corresponding GDALDataset. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
ARGDataset *poDS;
|
||||
|
||||
poDS = new ARGDataset();
|
||||
|
||||
poDS->pszFilename = CPLStrdup(poOpenInfo->pszFilename);
|
||||
poDS->SetMetadataItem("LAYER",pszLayer,NULL);
|
||||
poDS->nRasterXSize = nCols;
|
||||
poDS->nRasterYSize = nRows;
|
||||
poDS->SetProjection( pszWKT );
|
||||
|
||||
// done with the projection string
|
||||
CPLFree(pszWKT);
|
||||
CPLFree(pszLayer);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Assume ownership of the file handled from the GDALOpenInfo. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb");
|
||||
if (poDS->fpImage == NULL)
|
||||
{
|
||||
delete poDS;
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"Could not open dataset '%s'", poOpenInfo->pszFilename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
poDS->adfGeoTransform[0] = fXmin;
|
||||
poDS->adfGeoTransform[1] = fCellwidth;
|
||||
poDS->adfGeoTransform[2] = fXSkew;
|
||||
poDS->adfGeoTransform[3] = fYmax;
|
||||
poDS->adfGeoTransform[4] = fYSkew;
|
||||
poDS->adfGeoTransform[5] = -fCellheight;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create band information objects. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
RawRasterBand *poBand;
|
||||
|
||||
#ifdef CPL_LSB
|
||||
int bNative = FALSE;
|
||||
#else
|
||||
int bNative = TRUE;
|
||||
#endif
|
||||
|
||||
poBand = new RawRasterBand( poDS, 1, poDS->fpImage,
|
||||
0, nPixelOffset, nPixelOffset * nCols,
|
||||
eType, bNative, TRUE );
|
||||
poDS->SetBand( 1, poBand );
|
||||
|
||||
poBand->SetNoDataValue( fNoDataValue );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Initialize any PAM information. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poDS->SetDescription( poOpenInfo->pszFilename );
|
||||
poDS->TryLoadXML();
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Check for overviews. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
|
||||
|
||||
return( poDS );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* CreateCopy() */
|
||||
/************************************************************************/
|
||||
GDALDataset * ARGDataset::CreateCopy( const char * pszFilename,
|
||||
GDALDataset * poSrcDS,
|
||||
CPL_UNUSED int bStrict,
|
||||
CPL_UNUSED char ** papszOptions,
|
||||
CPL_UNUSED GDALProgressFunc pfnProgress,
|
||||
CPL_UNUSED void * pProgressData )
|
||||
{
|
||||
int nBands = poSrcDS->GetRasterCount();
|
||||
int nXSize = poSrcDS->GetRasterXSize();
|
||||
int nYSize = poSrcDS->GetRasterYSize();
|
||||
int nXBlockSize, nYBlockSize, nPixelOffset = 0;
|
||||
GDALDataType eType;
|
||||
CPLString osJSONFilename;
|
||||
CPLString pszDataType;
|
||||
json_object * poJSONObject = NULL;
|
||||
double adfTransform[6];
|
||||
GDALRasterBand * poSrcBand = NULL;
|
||||
RawRasterBand * poDstBand = NULL;
|
||||
VSILFILE * fpImage = NULL;
|
||||
void * pabyData;
|
||||
OGRSpatialReference oSRS;
|
||||
char * pszWKT = NULL;
|
||||
char ** pszTokens = NULL;
|
||||
const char * pszLayer = NULL;
|
||||
int nSrs = 0;
|
||||
OGRErr nErr = OGRERR_NONE;
|
||||
CPLErr eErr;
|
||||
|
||||
if( nBands != 1 )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_NotSupported,
|
||||
"ARG driver doesn't support %d bands. Must be 1 band.", nBands );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
|
||||
if( eType == GDT_Unknown ||
|
||||
eType == GDT_CInt16 ||
|
||||
eType == GDT_CInt32 ||
|
||||
eType == GDT_CFloat32 ||
|
||||
eType == GDT_CFloat64 )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_NotSupported,
|
||||
"ARG driver doesn't support data type %s.",
|
||||
GDALGetDataTypeName(eType) );
|
||||
return NULL;
|
||||
}
|
||||
else if (eType == GDT_Int16) {
|
||||
pszDataType = "int16";
|
||||
nPixelOffset = 2;
|
||||
}
|
||||
else if (eType == GDT_Int32) {
|
||||
pszDataType = "int32";
|
||||
nPixelOffset = 4;
|
||||
}
|
||||
else if (eType == GDT_Byte) {
|
||||
pszDataType = "uint8";
|
||||
nPixelOffset = 1;
|
||||
}
|
||||
else if (eType == GDT_UInt16) {
|
||||
pszDataType = "uint16";
|
||||
nPixelOffset = 2;
|
||||
}
|
||||
else if (eType == GDT_UInt32) {
|
||||
pszDataType = "uint32";
|
||||
nPixelOffset = 4;
|
||||
}
|
||||
else if (eType == GDT_Float32) {
|
||||
pszDataType = "float32";
|
||||
nPixelOffset = 4;
|
||||
}
|
||||
else if (eType == GDT_Float64) {
|
||||
pszDataType = "float64";
|
||||
nPixelOffset = 8;
|
||||
}
|
||||
|
||||
poSrcDS->GetGeoTransform( adfTransform );
|
||||
|
||||
pszWKT = (char *)poSrcDS->GetProjectionRef();
|
||||
nErr = oSRS.importFromWkt(&pszWKT);
|
||||
if (nErr != OGRERR_NONE) {
|
||||
CPLError( CE_Failure, CPLE_NotSupported,
|
||||
"Cannot import spatial reference WKT from source dataset.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (oSRS.GetAuthorityCode("PROJCS") != NULL) {
|
||||
nSrs = atoi(oSRS.GetAuthorityCode("PROJCS"));
|
||||
}
|
||||
else if (oSRS.GetAuthorityCode("GEOGCS") != NULL) {
|
||||
nSrs = atoi(oSRS.GetAuthorityCode("GEOGCS"));
|
||||
}
|
||||
else {
|
||||
// could not determine projected or geographic code
|
||||
// default to EPSG:3857 if no code could be found
|
||||
nSrs = 3857;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/* Create JSON companion file. */
|
||||
/********************************************************************/
|
||||
osJSONFilename = GetJsonFilename(pszFilename);
|
||||
|
||||
poJSONObject = json_object_new_object();
|
||||
|
||||
pszTokens = poSrcDS->GetMetadata();
|
||||
pszLayer = CSLFetchNameValue(pszTokens, "LAYER");
|
||||
|
||||
if ( pszLayer == NULL) {
|
||||
// Set the layer
|
||||
json_object_object_add(poJSONObject, "layer", json_object_new_string(
|
||||
CPLGetBasename(osJSONFilename)
|
||||
));
|
||||
}
|
||||
else {
|
||||
// Set the layer
|
||||
json_object_object_add(poJSONObject, "layer", json_object_new_string(
|
||||
pszLayer
|
||||
));
|
||||
}
|
||||
|
||||
// Set the type
|
||||
json_object_object_add(poJSONObject, "type", json_object_new_string("arg"));
|
||||
// Set the datatype
|
||||
json_object_object_add(poJSONObject, "datatype", json_object_new_string(pszDataType));
|
||||
// Set the number of rows
|
||||
json_object_object_add(poJSONObject, "rows", json_object_new_int(nYSize));
|
||||
// Set the number of columns
|
||||
json_object_object_add(poJSONObject, "cols", json_object_new_int(nXSize));
|
||||
// Set the xmin
|
||||
json_object_object_add(poJSONObject, "xmin", json_object_new_double(adfTransform[0]));
|
||||
// Set the ymax
|
||||
json_object_object_add(poJSONObject, "ymax", json_object_new_double(adfTransform[3]));
|
||||
// Set the cellwidth
|
||||
json_object_object_add(poJSONObject, "cellwidth", json_object_new_double(adfTransform[1]));
|
||||
// Set the cellheight
|
||||
json_object_object_add(poJSONObject, "cellheight", json_object_new_double(-adfTransform[5]));
|
||||
// Set the xmax
|
||||
json_object_object_add(poJSONObject, "xmax", json_object_new_double(adfTransform[0] + nXSize * adfTransform[1]));
|
||||
// Set the ymin
|
||||
json_object_object_add(poJSONObject, "ymin", json_object_new_double(adfTransform[3] + nYSize * adfTransform[5]));
|
||||
// Set the xskew
|
||||
json_object_object_add(poJSONObject, "xskew", json_object_new_double(adfTransform[2]));
|
||||
// Set the yskew
|
||||
json_object_object_add(poJSONObject, "yskew", json_object_new_double(adfTransform[4]));
|
||||
if (nSrs > 0) {
|
||||
// Set the epsg
|
||||
json_object_object_add(poJSONObject, "epsg", json_object_new_int(nSrs));
|
||||
}
|
||||
|
||||
if (json_object_to_file((char *)osJSONFilename.c_str(), poJSONObject) < 0) {
|
||||
CPLError( CE_Failure, CPLE_NotSupported,
|
||||
"ARG driver can't write companion file.");
|
||||
|
||||
json_object_put(poJSONObject);
|
||||
poJSONObject = NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
json_object_put(poJSONObject);
|
||||
poJSONObject = NULL;
|
||||
|
||||
fpImage = VSIFOpenL(pszFilename, "wb");
|
||||
if (fpImage == NULL)
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_NotSupported,
|
||||
"ARG driver can't create data file %s.", pszFilename);
|
||||
|
||||
// remove JSON file
|
||||
VSIUnlink( osJSONFilename.c_str() );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// only 1 raster band
|
||||
poSrcBand = poSrcDS->GetRasterBand( 1 );
|
||||
|
||||
#ifdef CPL_LSB
|
||||
int bNative = FALSE;
|
||||
#else
|
||||
int bNative = TRUE;
|
||||
#endif
|
||||
|
||||
poDstBand = new RawRasterBand( fpImage, 0, nPixelOffset,
|
||||
nPixelOffset * nXSize, eType, bNative,
|
||||
nXSize, nYSize, TRUE, FALSE);
|
||||
|
||||
poSrcBand->GetBlockSize(&nXBlockSize, &nYBlockSize);
|
||||
|
||||
pabyData = CPLMalloc(nXBlockSize * nPixelOffset);
|
||||
|
||||
// convert any blocks into scanlines
|
||||
for (int nYBlock = 0; nYBlock * nYBlockSize < nYSize; nYBlock++) {
|
||||
for (int nYScanline = 0; nYScanline < nYBlockSize; nYScanline++) {
|
||||
if ((nYScanline+1) + nYBlock * nYBlockSize > poSrcBand->GetYSize() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int nXBlock = 0; nXBlock * nXBlockSize < nXSize; nXBlock++) {
|
||||
int nXValid;
|
||||
|
||||
if( (nXBlock+1) * nXBlockSize > poSrcBand->GetXSize() )
|
||||
nXValid = poSrcBand->GetXSize() - nXBlock * nXBlockSize;
|
||||
else
|
||||
nXValid = nXBlockSize;
|
||||
|
||||
eErr = poSrcBand->RasterIO(GF_Read, nXBlock * nXBlockSize,
|
||||
nYBlock * nYBlockSize + nYScanline, nXValid, 1, pabyData, nXBlockSize,
|
||||
1, eType, 0, 0, NULL);
|
||||
|
||||
if (eErr != CE_None) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined, "Error reading.");
|
||||
|
||||
CPLFree( pabyData );
|
||||
delete poDstBand;
|
||||
VSIFCloseL( fpImage );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
eErr = poDstBand->RasterIO(GF_Write, nXBlock * nXBlockSize,
|
||||
nYBlock * nYBlockSize + nYScanline, nXValid, 1, pabyData, nXBlockSize,
|
||||
1, eType, 0, 0, NULL);
|
||||
|
||||
if (eErr != CE_None) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined, "Error writing.");
|
||||
|
||||
CPLFree( pabyData );
|
||||
delete poDstBand;
|
||||
VSIFCloseL( fpImage );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CPLFree( pabyData );
|
||||
delete poDstBand;
|
||||
VSIFCloseL( fpImage );
|
||||
|
||||
return (GDALDataset *)GDALOpen( pszFilename, GA_ReadOnly );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALRegister_ARG() */
|
||||
/************************************************************************/
|
||||
|
||||
void GDALRegister_ARG()
|
||||
{
|
||||
GDALDriver *poDriver;
|
||||
|
||||
if( GDALGetDriverByName( "ARG" ) == NULL )
|
||||
{
|
||||
poDriver = new GDALDriver();
|
||||
|
||||
poDriver->SetDescription( "ARG" );
|
||||
poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
|
||||
poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
|
||||
"Azavea Raster Grid format" );
|
||||
poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
|
||||
"frmt_various.html#ARG" );
|
||||
poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
|
||||
|
||||
poDriver->pfnIdentify = ARGDataset::Identify;
|
||||
poDriver->pfnOpen = ARGDataset::Open;
|
||||
poDriver->pfnCreateCopy = ARGDataset::CreateCopy;
|
||||
|
||||
GetGDALDriverManager()->RegisterDriver( poDriver );
|
||||
}
|
||||
}
|
||||
15
bazaar/plugin/gdal/frmts/arg/makefile.vc
Normal file
15
bazaar/plugin/gdal/frmts/arg/makefile.vc
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
OBJ = argdataset.obj
|
||||
|
||||
EXTRAFLAGS = -I..\..\ogr\ogrsf_frmts\geojson -I../../ogr/ogrsf_frmts/geojson/libjson -I..\raw
|
||||
|
||||
GDAL_ROOT = ..\..
|
||||
|
||||
!INCLUDE $(GDAL_ROOT)\nmake.opt
|
||||
|
||||
default: $(OBJ)
|
||||
xcopy /D /Y *.obj ..\o
|
||||
|
||||
clean:
|
||||
-del *.obj
|
||||
|
||||
15
bazaar/plugin/gdal/frmts/blx/GNUmakefile
Normal file
15
bazaar/plugin/gdal/frmts/blx/GNUmakefile
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
include ../../GDALmake.opt
|
||||
|
||||
XTRA_OPT = -I. -DGDALDRIVER
|
||||
|
||||
OBJ = blxdataset.o blx.o
|
||||
|
||||
CPPFLAGS := $(XTRA_OPT) $(CPPFLAGS)
|
||||
|
||||
default: $(OBJ:.o=.$(OBJ_EXT))
|
||||
|
||||
clean:
|
||||
rm -f *.o $(O_OBJ)
|
||||
|
||||
install-obj: $(O_OBJ:.o=.$(OBJ_EXT))
|
||||
1315
bazaar/plugin/gdal/frmts/blx/blx.c
Normal file
1315
bazaar/plugin/gdal/frmts/blx/blx.c
Normal file
File diff suppressed because it is too large
Load diff
147
bazaar/plugin/gdal/frmts/blx/blx.h
Normal file
147
bazaar/plugin/gdal/frmts/blx/blx.h
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/* libblx - Magellan BLX topo reader/writer library
|
||||
*
|
||||
* Copyright (c) 2008, Henrik Johansson <henrik@johome.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _BLX_H_INCLUDED
|
||||
#define _BLX_H_INCLUDED
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Constants */
|
||||
#define BLX_UNDEF -32768
|
||||
#define BLX_OVERVIEWLEVELS 4
|
||||
|
||||
/* Possible values of ctx.endian */
|
||||
#define BIGENDIAN 1
|
||||
#define LITTLEENDIAN 0
|
||||
|
||||
/* Data types */
|
||||
|
||||
typedef short int blxdata;
|
||||
|
||||
struct cellindex_s {
|
||||
int offset;
|
||||
unsigned int datasize; /* Uncompressed size */
|
||||
unsigned int compdatasize; /* Compressed data size */
|
||||
};
|
||||
|
||||
struct blxcontext_s {
|
||||
int xsize, ysize;
|
||||
int cell_xsize, cell_ysize;
|
||||
int cell_cols, cell_rows;
|
||||
double lon,lat;
|
||||
double pixelsize_lon, pixelsize_lat;
|
||||
|
||||
int zscale;
|
||||
int maxchunksize;
|
||||
int minval, maxval;
|
||||
|
||||
int endian;
|
||||
|
||||
struct cellindex_s *cellindex;
|
||||
|
||||
int debug;
|
||||
|
||||
int fillundef; /* If non-zero, fillundefval will be used instead of -32768 for undefined values in non-empty cells when
|
||||
a cell is written */
|
||||
int fillundefval;
|
||||
|
||||
FILE *fh;
|
||||
int write;
|
||||
int open;
|
||||
};
|
||||
|
||||
typedef struct blxcontext_s blxcontext_t;
|
||||
|
||||
struct component_s {
|
||||
int n;
|
||||
blxdata *lut;
|
||||
int dlen;
|
||||
blxdata *data;
|
||||
};
|
||||
|
||||
/* Included all functions in the global name space when testing */
|
||||
#ifdef TEST
|
||||
#define STATIC
|
||||
#else
|
||||
#define STATIC static
|
||||
#endif
|
||||
|
||||
/* Define memory allocation and I/O function macros */
|
||||
#ifdef GDALDRIVER
|
||||
#include "cpl_conv.h"
|
||||
#define BLXfopen VSIFOpen
|
||||
#define BLXfclose VSIFClose
|
||||
#define BLXfread VSIFRead
|
||||
#define BLXfwrite VSIFWrite
|
||||
#define BLXfseek VSIFSeek
|
||||
#define BLXftell VSIFTell
|
||||
#define BLXmalloc VSIMalloc
|
||||
#define BLXfree CPLFree
|
||||
#define BLXdebug0(text) CPLDebug("BLX", text)
|
||||
#define BLXdebug1(text, arg1) CPLDebug("BLX", text, arg1)
|
||||
#define BLXdebug2(text, arg1, arg2) CPLDebug("BLX", text, arg1, arg2)
|
||||
#define BLXerror0(text) CPLError(CE_Failure, CPLE_AppDefined, text)
|
||||
#define BLXnotice1(text, arg1) CPLDebug("BLX", text, arg1)
|
||||
#define BLXnotice2(text, arg1, arg2) CPLDebug("BLX", text, arg1, arg2)
|
||||
#else
|
||||
#define BLXfopen fopen
|
||||
#define BLXfclose fclose
|
||||
#define BLXfread fread
|
||||
#define BLXfwrite fwrite
|
||||
#define BLXfseek fseek
|
||||
#define BLXftell ftell
|
||||
#define BLXmalloc malloc
|
||||
#define BLXfree free
|
||||
#define BLXdebug0 printf
|
||||
#define BLXdebug1 printf
|
||||
#define BLXdebug2 printf
|
||||
#define BLXerror0 printf
|
||||
#define BLXnotice1 printf
|
||||
#define BLXnotice2 printf
|
||||
#endif
|
||||
|
||||
/* Function prototypes */
|
||||
#ifdef TEST
|
||||
STATIC int compress_chunk(unsigned char *inbuf, int inlen, unsigned char *outbuf, int outbuflen);
|
||||
STATIC int uncompress_chunk(unsigned char *inbuf, int inlen, unsigned char *outbuf, int outbuflen);
|
||||
STATIC blxdata *reconstruct_horiz(blxdata *base, blxdata *diff, unsigned rows, unsigned cols, blxdata *out);
|
||||
STATIC blxdata *reconstruct_vert(blxdata *base, blxdata *diff, unsigned rows, unsigned cols, blxdata *out);
|
||||
STATIC void decimate_horiz(blxdata *in, unsigned rows, unsigned cols, blxdata *base, blxdata *diff);
|
||||
STATIC void decimate_vert(blxdata *in, unsigned int rows, unsigned int cols, blxdata *base, blxdata *diff);
|
||||
STATIC blxdata *decode_celldata(blxcontext_t *blxcontext, unsigned char *inbuf, int len, int *side, blxdata *outbuf, int outbufsize, int overviewlevel);
|
||||
#endif
|
||||
|
||||
blxcontext_t *blx_create_context(void);
|
||||
void blx_free_context(blxcontext_t *ctx);
|
||||
int blxopen(blxcontext_t *ctx, const char *filename, const char *rw);
|
||||
int blxclose(blxcontext_t *ctx);
|
||||
void blxprintinfo(blxcontext_t *ctx);
|
||||
short *blx_readcell(blxcontext_t *ctx, int row, int col, short *buffer, int bufsize, int overviewlevel);
|
||||
int blx_encode_celldata(blxcontext_t *ctx, blxdata *indata, int side, unsigned char *outbuf, int outbufsize);
|
||||
int blx_checkheader(char *header);
|
||||
int blx_writecell(blxcontext_t *ctx, blxdata *cell, int cellrow, int cellcol);
|
||||
|
||||
#endif
|
||||
453
bazaar/plugin/gdal/frmts/blx/blxdataset.cpp
Normal file
453
bazaar/plugin/gdal/frmts/blx/blxdataset.cpp
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
/******************************************************************************
|
||||
* $Id: blxdataset.cpp 28053 2014-12-04 09:31:07Z rouault $
|
||||
*
|
||||
* Project: BLX Driver
|
||||
* Purpose: GDAL BLX support.
|
||||
* Author: Henrik Johansson, henrik@johome.net
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2006, Henrik Johansson <henrik@johome.net>
|
||||
* Copyright (c) 2008-2011, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************
|
||||
*
|
||||
*/
|
||||
|
||||
#include "gdal_pam.h"
|
||||
#include "cpl_string.h"
|
||||
|
||||
CPL_CVSID("$Id: blxdataset.cpp 28053 2014-12-04 09:31:07Z rouault $");
|
||||
|
||||
CPL_C_START
|
||||
#include <blx.h>
|
||||
CPL_C_END
|
||||
|
||||
CPL_C_START
|
||||
void GDALRegister_BLX(void);
|
||||
CPL_C_END
|
||||
|
||||
class BLXDataset : public GDALPamDataset
|
||||
{
|
||||
friend class BLXRasterBand;
|
||||
|
||||
CPLErr GetGeoTransform( double * padfTransform );
|
||||
const char *GetProjectionRef();
|
||||
|
||||
blxcontext_t *blxcontext;
|
||||
|
||||
int nOverviewCount;
|
||||
int bIsOverview;
|
||||
BLXDataset *papoOverviewDS[BLX_OVERVIEWLEVELS];
|
||||
|
||||
public:
|
||||
BLXDataset();
|
||||
~BLXDataset();
|
||||
|
||||
static GDALDataset *Open( GDALOpenInfo * );
|
||||
};
|
||||
|
||||
class BLXRasterBand : public GDALPamRasterBand
|
||||
{
|
||||
int overviewLevel;
|
||||
public:
|
||||
BLXRasterBand( BLXDataset *, int, int overviewLevel=0 );
|
||||
|
||||
virtual double GetNoDataValue( int *pbSuccess = NULL );
|
||||
virtual GDALColorInterp GetColorInterpretation(void);
|
||||
virtual int GetOverviewCount();
|
||||
virtual GDALRasterBand *GetOverview( int );
|
||||
|
||||
virtual CPLErr IReadBlock( int, int, void * );
|
||||
};
|
||||
|
||||
GDALDataset *BLXDataset::Open( GDALOpenInfo * poOpenInfo )
|
||||
|
||||
{
|
||||
// --------------------------------------------------------------------
|
||||
// First that the header looks like a BLX header
|
||||
// --------------------------------------------------------------------
|
||||
if( poOpenInfo->fpL == NULL || poOpenInfo->nHeaderBytes < 102 )
|
||||
return NULL;
|
||||
|
||||
if(!blx_checkheader((char *)poOpenInfo->pabyHeader))
|
||||
return NULL;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Create a corresponding GDALDataset.
|
||||
// --------------------------------------------------------------------
|
||||
BLXDataset *poDS;
|
||||
|
||||
poDS = new BLXDataset();
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Open BLX file
|
||||
// --------------------------------------------------------------------
|
||||
poDS->blxcontext = blx_create_context();
|
||||
if(poDS->blxcontext==NULL)
|
||||
{
|
||||
delete poDS;
|
||||
return NULL;
|
||||
}
|
||||
if (blxopen(poDS->blxcontext, poOpenInfo->pszFilename, "rb") != 0)
|
||||
{
|
||||
delete poDS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((poDS->blxcontext->cell_xsize % (1 << (1+BLX_OVERVIEWLEVELS))) != 0 ||
|
||||
(poDS->blxcontext->cell_ysize % (1 << (1+BLX_OVERVIEWLEVELS))) != 0)
|
||||
{
|
||||
delete poDS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Update dataset header from BLX context
|
||||
poDS->nRasterXSize = poDS->blxcontext->xsize;
|
||||
poDS->nRasterYSize = poDS->blxcontext->ysize;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Create band information objects.
|
||||
// --------------------------------------------------------------------
|
||||
poDS->nBands = 1;
|
||||
poDS->SetBand( 1, new BLXRasterBand( poDS, 1 ));
|
||||
|
||||
// Create overview bands
|
||||
poDS->nOverviewCount = BLX_OVERVIEWLEVELS;
|
||||
for(int i=0; i < poDS->nOverviewCount; i++) {
|
||||
poDS->papoOverviewDS[i] = new BLXDataset();
|
||||
poDS->papoOverviewDS[i]->blxcontext = poDS->blxcontext;
|
||||
poDS->papoOverviewDS[i]->bIsOverview = TRUE;
|
||||
poDS->papoOverviewDS[i]->nRasterXSize = poDS->nRasterXSize >> (i+1);
|
||||
poDS->papoOverviewDS[i]->nRasterYSize = poDS->nRasterYSize >> (i+1);
|
||||
poDS->nBands = 1;
|
||||
poDS->papoOverviewDS[i]->SetBand(1, new BLXRasterBand( poDS->papoOverviewDS[i], 1, i+1));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Confirm the requested access is supported. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( poOpenInfo->eAccess == GA_Update )
|
||||
{
|
||||
delete poDS;
|
||||
CPLError( CE_Failure, CPLE_NotSupported,
|
||||
"The BLX driver does not support update access to existing"
|
||||
" datasets.\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Initialize any PAM information. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poDS->SetDescription( poOpenInfo->pszFilename );
|
||||
poDS->TryLoadXML();
|
||||
|
||||
return( poDS );
|
||||
}
|
||||
|
||||
BLXDataset::BLXDataset() {
|
||||
blxcontext = NULL;
|
||||
bIsOverview = FALSE;
|
||||
nOverviewCount = 0;
|
||||
|
||||
for(int i=0; i < nOverviewCount; i++)
|
||||
papoOverviewDS[i]=NULL;
|
||||
}
|
||||
|
||||
BLXDataset::~BLXDataset() {
|
||||
if(!bIsOverview) {
|
||||
if(blxcontext) {
|
||||
blxclose(blxcontext);
|
||||
blx_free_context(blxcontext);
|
||||
}
|
||||
for(int i=0; i < nOverviewCount; i++)
|
||||
if(papoOverviewDS[i])
|
||||
delete papoOverviewDS[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CPLErr BLXDataset::GetGeoTransform( double * padfTransform )
|
||||
|
||||
{
|
||||
padfTransform[0] = blxcontext->lon;
|
||||
padfTransform[1] = blxcontext->pixelsize_lon;
|
||||
padfTransform[2] = 0.0;
|
||||
padfTransform[3] = blxcontext->lat;
|
||||
padfTransform[4] = 0.0;
|
||||
padfTransform[5] = blxcontext->pixelsize_lat;
|
||||
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
const char *BLXDataset::GetProjectionRef()
|
||||
{
|
||||
return( "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]]" );
|
||||
}
|
||||
|
||||
BLXRasterBand::BLXRasterBand( BLXDataset *poDS, int nBand, int overviewLevel )
|
||||
|
||||
{
|
||||
BLXDataset *poGDS = (BLXDataset *) poDS;
|
||||
|
||||
this->poDS = poDS;
|
||||
this->nBand = nBand;
|
||||
this->overviewLevel = overviewLevel;
|
||||
|
||||
eDataType = GDT_Int16;
|
||||
|
||||
nBlockXSize = poGDS->blxcontext->cell_xsize >> overviewLevel;
|
||||
nBlockYSize = poGDS->blxcontext->cell_ysize >> overviewLevel;
|
||||
}
|
||||
|
||||
int BLXRasterBand::GetOverviewCount()
|
||||
{
|
||||
BLXDataset *poGDS = (BLXDataset *) poDS;
|
||||
|
||||
return poGDS->nOverviewCount;
|
||||
}
|
||||
|
||||
GDALRasterBand *BLXRasterBand::GetOverview( int i )
|
||||
{
|
||||
BLXDataset *poGDS = (BLXDataset *) poDS;
|
||||
|
||||
if( i < 0 || i >= poGDS->nOverviewCount )
|
||||
return NULL;
|
||||
else
|
||||
return poGDS->papoOverviewDS[i]->GetRasterBand(nBand);
|
||||
}
|
||||
|
||||
CPLErr BLXRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
|
||||
void * pImage )
|
||||
|
||||
{
|
||||
BLXDataset *poGDS = (BLXDataset *) poDS;
|
||||
|
||||
if(blx_readcell(poGDS->blxcontext, nBlockYOff, nBlockXOff, (short *)pImage, nBlockXSize*nBlockYSize*2, overviewLevel) == NULL) {
|
||||
CPLError(CE_Failure, CPLE_AppDefined,
|
||||
"Failed to read BLX cell");
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
double BLXRasterBand::GetNoDataValue( int * pbSuccess )
|
||||
{
|
||||
if (pbSuccess)
|
||||
*pbSuccess = TRUE;
|
||||
return BLX_UNDEF;
|
||||
}
|
||||
|
||||
GDALColorInterp BLXRasterBand::GetColorInterpretation(void) {
|
||||
return GCI_GrayIndex;
|
||||
}
|
||||
|
||||
/* TODO: check if georeference is the same as for BLX files, WGS84
|
||||
*/
|
||||
static GDALDataset *
|
||||
BLXCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
|
||||
int bStrict, char ** papszOptions,
|
||||
GDALProgressFunc pfnProgress, void * pProgressData )
|
||||
|
||||
{
|
||||
int nBands = poSrcDS->GetRasterCount();
|
||||
int nXSize = poSrcDS->GetRasterXSize();
|
||||
int nYSize = poSrcDS->GetRasterYSize();
|
||||
|
||||
int zscale = 1;
|
||||
int fillundef = 1, fillundefval = 0;
|
||||
int endian = LITTLEENDIAN;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Some rudimentary checks
|
||||
// --------------------------------------------------------------------
|
||||
if( nBands != 1 )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_NotSupported,
|
||||
"BLX driver doesn't support %d bands. Must be 1 (grey) ",
|
||||
nBands );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Int16 && bStrict )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_NotSupported,
|
||||
"BLX driver doesn't support data type %s. "
|
||||
"Only 16 bit byte bands supported.\n",
|
||||
GDALGetDataTypeName(
|
||||
poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( (nXSize % 128 != 0) || (nYSize % 128 != 0) ) {
|
||||
CPLError( CE_Failure, CPLE_NotSupported,
|
||||
"BLX driver doesn't support dimensions that are not a multiple of 128.\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// What options has the user selected?
|
||||
// --------------------------------------------------------------------
|
||||
if( CSLFetchNameValue(papszOptions,"ZSCALE") != NULL ) {
|
||||
zscale = atoi(CSLFetchNameValue(papszOptions,"ZSCALE"));
|
||||
if( zscale < 1 ) {
|
||||
CPLError( CE_Failure, CPLE_IllegalArg,
|
||||
"ZSCALE=%s is not a legal value in the range >= 1.",
|
||||
CSLFetchNameValue(papszOptions,"ZSCALE") );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( CSLFetchNameValue(papszOptions,"FILLUNDEF") != NULL
|
||||
&& EQUAL(CSLFetchNameValue(papszOptions,"FILLUNDEF"),"NO") )
|
||||
fillundef = 0;
|
||||
else
|
||||
fillundef = 1;
|
||||
|
||||
if( CSLFetchNameValue(papszOptions,"FILLUNDEFVAL") != NULL ) {
|
||||
fillundefval = atoi(CSLFetchNameValue(papszOptions,"FILLUNDEFVAL"));
|
||||
if( (fillundefval < -32768) || (fillundefval > 32767) ) {
|
||||
CPLError( CE_Failure, CPLE_IllegalArg,
|
||||
"FILLUNDEFVAL=%s is not a legal value in the range -32768, 32767.",
|
||||
CSLFetchNameValue(papszOptions,"FILLUNDEFVAL") );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if( CSLFetchNameValue(papszOptions,"BIGENDIAN") != NULL
|
||||
&& !EQUAL(CSLFetchNameValue(papszOptions,"BIGENDIAN"),"NO") )
|
||||
endian = BIGENDIAN;
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Create the dataset.
|
||||
// --------------------------------------------------------------------
|
||||
blxcontext_t *ctx;
|
||||
|
||||
// Create a BLX context
|
||||
ctx = blx_create_context();
|
||||
|
||||
// Setup BLX parameters
|
||||
ctx->cell_rows = nYSize / ctx->cell_ysize;
|
||||
ctx->cell_cols = nXSize / ctx->cell_xsize;
|
||||
ctx->zscale = zscale;
|
||||
ctx->fillundef = fillundef;
|
||||
ctx->fillundefval = fillundefval;
|
||||
ctx->endian = endian;
|
||||
|
||||
if(blxopen(ctx, pszFilename, "wb")) {
|
||||
CPLError( CE_Failure, CPLE_OpenFailed,
|
||||
"Unable to create blx file %s.\n",
|
||||
pszFilename );
|
||||
blx_free_context(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Loop over image, copying image data.
|
||||
// --------------------------------------------------------------------
|
||||
GInt16 *pabyTile;
|
||||
CPLErr eErr=CE_None;
|
||||
|
||||
pabyTile = (GInt16 *) VSIMalloc( sizeof(GInt16)*ctx->cell_xsize*ctx->cell_ysize );
|
||||
if (pabyTile == NULL)
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
|
||||
blxclose(ctx);
|
||||
blx_free_context(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !pfnProgress( 0.0, NULL, pProgressData ) )
|
||||
eErr = CE_Failure;
|
||||
|
||||
for(int i=0; (i < ctx->cell_rows) && (eErr == CE_None); i++)
|
||||
for(int j=0; j < ctx->cell_cols; j++) {
|
||||
blxdata *celldata;
|
||||
GDALRasterBand * poBand = poSrcDS->GetRasterBand( 1 );
|
||||
eErr = poBand->RasterIO( GF_Read, j*ctx->cell_xsize, i*ctx->cell_ysize,
|
||||
ctx->cell_xsize, ctx->cell_ysize,
|
||||
pabyTile, ctx->cell_xsize, ctx->cell_ysize, GDT_Int16,
|
||||
0, 0, NULL );
|
||||
if(eErr >= CE_Failure)
|
||||
break;
|
||||
celldata = pabyTile;
|
||||
if (blx_writecell(ctx, celldata, i, j) != 0)
|
||||
{
|
||||
eErr = CE_Failure;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! pfnProgress( 1.0 * (i * ctx->cell_cols + j) / (ctx->cell_rows * ctx->cell_cols), NULL, pProgressData ))
|
||||
{
|
||||
eErr = CE_Failure;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pfnProgress( 1.0, NULL, pProgressData );
|
||||
|
||||
CPLFree( pabyTile );
|
||||
|
||||
double adfGeoTransform[6];
|
||||
if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
|
||||
{
|
||||
ctx->lon = adfGeoTransform[0];
|
||||
ctx->lat = adfGeoTransform[3];
|
||||
ctx->pixelsize_lon = adfGeoTransform[1];
|
||||
ctx->pixelsize_lat = adfGeoTransform[5];
|
||||
}
|
||||
|
||||
blxclose(ctx);
|
||||
blx_free_context(ctx);
|
||||
|
||||
if (eErr == CE_None)
|
||||
return (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void GDALRegister_BLX()
|
||||
|
||||
{
|
||||
GDALDriver *poDriver;
|
||||
|
||||
if( GDALGetDriverByName( "BLX" ) == NULL )
|
||||
{
|
||||
poDriver = new GDALDriver();
|
||||
|
||||
poDriver->SetDescription( "BLX" );
|
||||
poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
|
||||
poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
|
||||
"Magellan topo (.blx)" );
|
||||
poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
|
||||
"frmt_various.html#BLX" );
|
||||
poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "blx" );
|
||||
|
||||
poDriver->pfnOpen = BLXDataset::Open;
|
||||
poDriver->pfnCreateCopy = BLXCreateCopy;
|
||||
|
||||
GetGDALDriverManager()->RegisterDriver( poDriver );
|
||||
}
|
||||
}
|
||||
|
||||
48
bazaar/plugin/gdal/frmts/blx/frmt_blx.html
Normal file
48
bazaar/plugin/gdal/frmts/blx/frmt_blx.html
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>BLX -- Magellan BLX Topo File Format (available from GDAL 1.6.0)</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff">
|
||||
|
||||
<h1>BLX -- Magellan BLX Topo File Format</h1>
|
||||
|
||||
<p>
|
||||
BLX is the format for storing topographic data in Magellan GPS units. This driver
|
||||
supports both reading and writing. In addition the 4 overview levels inherent in
|
||||
the BLX format can be used with the driver.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The BLX format is tile based, for the moment the tile size is fixed to 128x128 size. Furthermore the dimensions must be a multiple of the tile size.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The data type is fixed to Int16 and the value for undefined values is fixed to -32768. In the BLX format undefined values are only really supported on tile level. For
|
||||
undefined pixels in non-empty tiles see the FILLUNDEF/FILLUNDEFVAL options.
|
||||
</p>
|
||||
|
||||
<h2>Georeferencing</h2>
|
||||
|
||||
<p>
|
||||
The BLX projection is fixed to WGS84 and georeferencing from BLX is supported in the form of one tiepoint and
|
||||
pixelsize.
|
||||
</p>
|
||||
|
||||
<h2>Creation Issues</h2>
|
||||
|
||||
Creation Options:
|
||||
<p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li> <b>ZSCALE=1</b>: Set the desired quantization increment for write access. A higher value will result in better compression and lower vertical resolution.
|
||||
<li> <b>BIGENDIAN=YES</b>: If BIGENDIAN is defined, the output file will be in XLB format (big endian blx).
|
||||
<li> <b>FILLUNDEF=YES</b>: If FILLUNDEF is yes the value of FILLUNDEFVAL will be used instead of -32768 for non-empty tiles. This is needed since the BLX format only support undefined values for full tiles, not individual pixels.
|
||||
<li> <b>FILLUNDEFVAL=0</b>: See FILLUNDEF
|
||||
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
15
bazaar/plugin/gdal/frmts/blx/makefile.vc
Normal file
15
bazaar/plugin/gdal/frmts/blx/makefile.vc
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
OBJ = blxdataset.obj blx.obj
|
||||
|
||||
GDAL_ROOT = ..\..
|
||||
|
||||
!INCLUDE $(GDAL_ROOT)\nmake.opt
|
||||
|
||||
EXTRAFLAGS = -I. -DGDALDRIVER
|
||||
|
||||
default: $(OBJ)
|
||||
xcopy /D /Y *.obj ..\o
|
||||
|
||||
clean:
|
||||
-del *.obj
|
||||
|
||||
13
bazaar/plugin/gdal/frmts/bmp/GNUmakefile
Normal file
13
bazaar/plugin/gdal/frmts/bmp/GNUmakefile
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
include ../../GDALmake.opt
|
||||
|
||||
OBJ = bmpdataset.o
|
||||
|
||||
|
||||
|
||||
default: $(OBJ:.o=.$(OBJ_EXT))
|
||||
|
||||
clean:
|
||||
rm -f *.o $(O_OBJ)
|
||||
|
||||
install-obj: $(O_OBJ:.o=.$(OBJ_EXT))
|
||||
1553
bazaar/plugin/gdal/frmts/bmp/bmpdataset.cpp
Normal file
1553
bazaar/plugin/gdal/frmts/bmp/bmpdataset.cpp
Normal file
File diff suppressed because it is too large
Load diff
45
bazaar/plugin/gdal/frmts/bmp/frmt_bmp.html
Normal file
45
bazaar/plugin/gdal/frmts/bmp/frmt_bmp.html
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>BMP --- Microsoft Windows Device Independent Bitmap</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff">
|
||||
|
||||
<h1>BMP --- Microsoft Windows Device Independent Bitmap</h1>
|
||||
|
||||
MS Windows Device Independent Bitmaps supported by the Windows kernel and
|
||||
mostly used for storing system decoration images. Due to the nature of the
|
||||
BMP format it has several restrictions and could not be used for general image
|
||||
storing. In particular, you can create only 1-bit monochrome,
|
||||
8-bit pseudocoloured and 24-bit RGB images only. Even grayscale images must
|
||||
be saved in pseudocolour form.<p>
|
||||
|
||||
This driver supports reading almost any type of the BMP files and could write
|
||||
ones which should be supported on any Windows system. Only single- or three-
|
||||
band files could be saved in BMP file. Input values will be resampled to 8
|
||||
bit.<p>
|
||||
|
||||
If an ESRI world file exists with the .bpw, .bmpw or .wld extension, it will be read and
|
||||
used to establish the geotransform for the image.<p>
|
||||
|
||||
<h2>Creation Options</h2>
|
||||
<ul>
|
||||
<li> <b>WORLDFILE=YES</b>: Force the generation of an associated
|
||||
ESRI world file (with the extension .wld).
|
||||
<p>
|
||||
</ul>
|
||||
|
||||
<h2>See Also:</h2>
|
||||
|
||||
<ul>
|
||||
<li> Implemented as <tt>gdal/frmts/bmp/bmpdataset.cpp</tt>.<p>
|
||||
|
||||
<li> <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_9qg5.asp">
|
||||
MSDN Bitmap Reference
|
||||
</a><p>
|
||||
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
13
bazaar/plugin/gdal/frmts/bmp/makefile.vc
Normal file
13
bazaar/plugin/gdal/frmts/bmp/makefile.vc
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
OBJ = bmpdataset.obj
|
||||
|
||||
GDAL_ROOT = ..\..
|
||||
|
||||
!INCLUDE $(GDAL_ROOT)\nmake.opt
|
||||
|
||||
default: $(OBJ)
|
||||
xcopy /D /Y *.obj ..\o
|
||||
|
||||
clean:
|
||||
-del *.obj
|
||||
|
||||
361
bazaar/plugin/gdal/frmts/bpg/bpgdataset.cpp
Normal file
361
bazaar/plugin/gdal/frmts/bpg/bpgdataset.cpp
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
/******************************************************************************
|
||||
* $Id$
|
||||
*
|
||||
* Project: GDAL BPG Driver
|
||||
* Purpose: Implement GDAL BPG Support based on libbpg
|
||||
* Author: Even Rouault, <even dot rouault at spatialys dot com>
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2014, Even Rouault <even dot rouault at spatialys dot com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "gdal_pam.h"
|
||||
#include "cpl_string.h"
|
||||
|
||||
// NOTE: build instructions
|
||||
// bpg Makefile needs to be modified to have -fPIC on CFLAGS:= at line 49 and LDFLAGS at line 54 before building bpg
|
||||
// g++ -fPIC -g -Wall -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -I/home/even/libbpg-0.9.4 frmts/bpg/bpgdataset.cpp -shared -o gdal_BPG.so -L. -lgdal -L/home/even/libbpg-0.9.4/ -lbpg
|
||||
|
||||
CPL_C_START
|
||||
#include "libbpg.h"
|
||||
CPL_C_END
|
||||
|
||||
CPL_CVSID("$Id$");
|
||||
|
||||
CPL_C_START
|
||||
void GDALRegister_BPG(void);
|
||||
CPL_C_END
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* BPGDataset */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
class BPGRasterBand;
|
||||
|
||||
class BPGDataset : public GDALPamDataset
|
||||
{
|
||||
friend class BPGRasterBand;
|
||||
|
||||
VSILFILE* fpImage;
|
||||
GByte* pabyUncompressed;
|
||||
int bHasBeenUncompressed;
|
||||
CPLErr eUncompressErrRet;
|
||||
CPLErr Uncompress();
|
||||
|
||||
public:
|
||||
BPGDataset();
|
||||
~BPGDataset();
|
||||
|
||||
static GDALDataset *Open( GDALOpenInfo * );
|
||||
static int Identify( GDALOpenInfo * );
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* BPGRasterBand */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
class BPGRasterBand : public GDALPamRasterBand
|
||||
{
|
||||
friend class BPGDataset;
|
||||
|
||||
public:
|
||||
|
||||
BPGRasterBand( BPGDataset *, int nbits );
|
||||
|
||||
virtual CPLErr IReadBlock( int, int, void * );
|
||||
virtual GDALColorInterp GetColorInterpretation();
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* BPGRasterBand() */
|
||||
/************************************************************************/
|
||||
|
||||
BPGRasterBand::BPGRasterBand( BPGDataset *poDS, int nbits )
|
||||
{
|
||||
this->poDS = poDS;
|
||||
|
||||
eDataType = (nbits > 8) ? GDT_UInt16 : GDT_Byte;
|
||||
|
||||
nBlockXSize = poDS->nRasterXSize;
|
||||
nBlockYSize = 1;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* IReadBlock() */
|
||||
/************************************************************************/
|
||||
|
||||
CPLErr BPGRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff, int nBlockYOff,
|
||||
void * pImage )
|
||||
{
|
||||
BPGDataset* poGDS = (BPGDataset*) poDS;
|
||||
|
||||
if( poGDS->Uncompress() != CE_None )
|
||||
return CE_Failure;
|
||||
|
||||
int i;
|
||||
int iBand = nBand;
|
||||
if( poGDS->nBands == 2 )
|
||||
iBand = 4;
|
||||
if( eDataType == GDT_Byte )
|
||||
{
|
||||
GByte* pabyUncompressed =
|
||||
&poGDS->pabyUncompressed[nBlockYOff * nRasterXSize * poGDS->nBands + iBand - 1];
|
||||
for(i=0;i<nRasterXSize;i++)
|
||||
((GByte*)pImage)[i] = pabyUncompressed[poGDS->nBands * i];
|
||||
}
|
||||
else
|
||||
{
|
||||
GUInt16* pasUncompressed = (GUInt16*)
|
||||
&poGDS->pabyUncompressed[(nBlockYOff * nRasterXSize * poGDS->nBands + iBand - 1) * 2];
|
||||
for(i=0;i<nRasterXSize;i++)
|
||||
((GUInt16*)pImage)[i] = pasUncompressed[poGDS->nBands * i];
|
||||
}
|
||||
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GetColorInterpretation() */
|
||||
/************************************************************************/
|
||||
|
||||
GDALColorInterp BPGRasterBand::GetColorInterpretation()
|
||||
|
||||
{
|
||||
BPGDataset* poGDS = (BPGDataset*) poDS;
|
||||
if( poGDS->nBands >= 3 )
|
||||
return (GDALColorInterp) (GCI_RedBand + (nBand - 1));
|
||||
else if( nBand == 1 )
|
||||
return GCI_GrayIndex;
|
||||
else
|
||||
return GCI_AlphaBand;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* BPGDataset */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* BPGDataset() */
|
||||
/************************************************************************/
|
||||
|
||||
BPGDataset::BPGDataset()
|
||||
|
||||
{
|
||||
fpImage = NULL;
|
||||
pabyUncompressed = NULL;
|
||||
bHasBeenUncompressed = FALSE;
|
||||
eUncompressErrRet = CE_None;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ~BPGDataset() */
|
||||
/************************************************************************/
|
||||
|
||||
BPGDataset::~BPGDataset()
|
||||
|
||||
{
|
||||
FlushCache();
|
||||
if (fpImage)
|
||||
VSIFCloseL(fpImage);
|
||||
VSIFree(pabyUncompressed);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Uncompress() */
|
||||
/************************************************************************/
|
||||
|
||||
CPLErr BPGDataset::Uncompress()
|
||||
{
|
||||
if (bHasBeenUncompressed)
|
||||
return eUncompressErrRet;
|
||||
bHasBeenUncompressed = TRUE;
|
||||
eUncompressErrRet = CE_Failure;
|
||||
|
||||
int nOutBands = (nBands < 3) ? nBands + 2 : nBands;
|
||||
int nDTSize = ( GetRasterBand(1)->GetRasterDataType() == GDT_Byte ) ? 1 : 2;
|
||||
pabyUncompressed = (GByte*)VSIMalloc3(nRasterXSize, nRasterYSize,
|
||||
nOutBands * nDTSize);
|
||||
if (pabyUncompressed == NULL)
|
||||
return CE_Failure;
|
||||
|
||||
VSIFSeekL(fpImage, 0, SEEK_END);
|
||||
vsi_l_offset nSize = VSIFTellL(fpImage);
|
||||
if (nSize != (vsi_l_offset)(int)nSize)
|
||||
return CE_Failure;
|
||||
VSIFSeekL(fpImage, 0, SEEK_SET);
|
||||
uint8_t* pabyCompressed = (uint8_t*)VSIMalloc(nSize);
|
||||
if (pabyCompressed == NULL)
|
||||
return CE_Failure;
|
||||
VSIFReadL(pabyCompressed, 1, nSize, fpImage);
|
||||
|
||||
BPGDecoderContext* ctxt = bpg_decoder_open();
|
||||
if( ctxt == NULL )
|
||||
{
|
||||
VSIFree(pabyCompressed);
|
||||
return CE_Failure;
|
||||
}
|
||||
BPGDecoderOutputFormat eOutputFormat;
|
||||
|
||||
if( GetRasterBand(1)->GetRasterDataType() == GDT_Byte )
|
||||
eOutputFormat = (nBands == 1 || nBands == 3) ? BPG_OUTPUT_FORMAT_RGB24 :
|
||||
BPG_OUTPUT_FORMAT_RGBA32;
|
||||
else
|
||||
eOutputFormat = (nBands == 1 || nBands == 3) ? BPG_OUTPUT_FORMAT_RGB48 :
|
||||
BPG_OUTPUT_FORMAT_RGBA64;
|
||||
if( bpg_decoder_decode(ctxt, pabyCompressed, (int)nSize) < 0 ||
|
||||
bpg_decoder_start(ctxt, eOutputFormat) < 0 )
|
||||
{
|
||||
bpg_decoder_close(ctxt);
|
||||
VSIFree(pabyCompressed);
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
for(int i=0;i<nRasterYSize;i++)
|
||||
{
|
||||
void* pRow = pabyUncompressed + i * nBands * nRasterXSize * nDTSize;
|
||||
if( bpg_decoder_get_line(ctxt, pRow) < 0 )
|
||||
{
|
||||
bpg_decoder_close(ctxt);
|
||||
VSIFree(pabyCompressed);
|
||||
return CE_Failure;
|
||||
}
|
||||
}
|
||||
|
||||
bpg_decoder_close(ctxt);
|
||||
VSIFree(pabyCompressed);
|
||||
|
||||
eUncompressErrRet = CE_None;
|
||||
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Identify() */
|
||||
/************************************************************************/
|
||||
|
||||
int BPGDataset::Identify( GDALOpenInfo * poOpenInfo )
|
||||
|
||||
{
|
||||
if( poOpenInfo->nHeaderBytes < BPG_DECODER_INFO_BUF_SIZE )
|
||||
return FALSE;
|
||||
|
||||
return memcmp(poOpenInfo->pabyHeader, "BPG\xfb", 4) == 0;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Open() */
|
||||
/************************************************************************/
|
||||
|
||||
GDALDataset *BPGDataset::Open( GDALOpenInfo * poOpenInfo )
|
||||
|
||||
{
|
||||
if( !Identify( poOpenInfo ) || poOpenInfo->fpL == NULL )
|
||||
return NULL;
|
||||
|
||||
BPGImageInfo imageInfo;
|
||||
if( bpg_decoder_get_info_from_buf(&imageInfo, NULL,
|
||||
poOpenInfo->pabyHeader,
|
||||
poOpenInfo->nHeaderBytes) < 0 )
|
||||
return NULL;
|
||||
|
||||
if( poOpenInfo->eAccess == GA_Update )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_NotSupported,
|
||||
"The BPG driver does not support update access to existing"
|
||||
" datasets.\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create a corresponding GDALDataset. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
BPGDataset *poDS;
|
||||
|
||||
poDS = new BPGDataset();
|
||||
poDS->nRasterXSize = imageInfo.width;
|
||||
poDS->nRasterYSize = imageInfo.height;
|
||||
poDS->fpImage = poOpenInfo->fpL;
|
||||
poOpenInfo->fpL = NULL;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create band information objects. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
int nBands = ( imageInfo.format == BPG_FORMAT_GRAY ) ? 1 : 3;
|
||||
if( imageInfo.has_alpha )
|
||||
nBands ++;
|
||||
|
||||
for( int iBand = 0; iBand < nBands; iBand++ )
|
||||
poDS->SetBand( iBand+1, new BPGRasterBand( poDS, imageInfo.bit_depth ) );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Initialize any PAM information. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poDS->SetDescription( poOpenInfo->pszFilename );
|
||||
|
||||
poDS->TryLoadXML( poOpenInfo->GetSiblingFiles() );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Open overviews. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename,
|
||||
poOpenInfo->GetSiblingFiles() );
|
||||
|
||||
return poDS;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALRegister_BPG() */
|
||||
/************************************************************************/
|
||||
|
||||
void GDALRegister_BPG()
|
||||
|
||||
{
|
||||
GDALDriver *poDriver;
|
||||
|
||||
if( GDALGetDriverByName( "BPG" ) == NULL )
|
||||
{
|
||||
poDriver = new GDALDriver();
|
||||
|
||||
poDriver->SetDescription( "BPG" );
|
||||
poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
|
||||
poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
|
||||
"Better Portable Graphics" );
|
||||
poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
|
||||
"frmt_bpg.html" );
|
||||
poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "bpg" );
|
||||
//poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/bpg" );
|
||||
|
||||
poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
|
||||
|
||||
poDriver->pfnIdentify = BPGDataset::Identify;
|
||||
poDriver->pfnOpen = BPGDataset::Open;
|
||||
|
||||
GetGDALDriverManager()->RegisterDriver( poDriver );
|
||||
}
|
||||
}
|
||||
37
bazaar/plugin/gdal/frmts/bsb/GNUmakefile
Normal file
37
bazaar/plugin/gdal/frmts/bsb/GNUmakefile
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
|
||||
VERSION = 1.3
|
||||
|
||||
include ../../GDALmake.opt
|
||||
|
||||
OBJ = bsb_read.o bsbdataset.o
|
||||
|
||||
DISTDIR = bsb-$(VERSION)
|
||||
|
||||
|
||||
|
||||
default: $(OBJ:.o=.$(OBJ_EXT))
|
||||
|
||||
clean:
|
||||
rm -f *.o $(O_OBJ)
|
||||
|
||||
bsb2raw$(EXE): bsb2raw.$(OBJ_EXT)
|
||||
$(LD) $(LDFLAGS) bsb2raw.$(OBJ_EXT) $(CONFIG_LIBS) -o bsb2raw$(EXE)
|
||||
|
||||
|
||||
install-obj: $(O_OBJ:.o=.$(OBJ_EXT))
|
||||
|
||||
dist:
|
||||
rm -rf $(DISTDIR)
|
||||
mkdir $(DISTDIR)
|
||||
cp *.cpp *.c *.h $(DISTDIR)
|
||||
rm $(DISTDIR)/bsbdataset.cpp
|
||||
cp Makefile.dist $(DISTDIR)/Makefile
|
||||
cp README.dist $(DISTDIR)/README
|
||||
cp ../../port/{cpl_error*,cpl_port*,cpl_string*} $(DISTDIR)
|
||||
cp ../../port/{cpl_vsisimple.cpp,cpl_config.h.in} $(DISTDIR)
|
||||
cp ../../port/{cpl_vsi.h,cpl_conv.*,cpl_path.cpp} $(DISTDIR)
|
||||
cp ../../port/cpl_config.h.in $(DISTDIR)/cpl_config.h
|
||||
rm $(DISTDIR)/*.o
|
||||
tar czf $(DISTDIR).tar.gz $(DISTDIR)
|
||||
zip -r $(DISTDIR).zip $(DISTDIR)
|
||||
2
bazaar/plugin/gdal/frmts/bsb/Makefile.dist
Normal file
2
bazaar/plugin/gdal/frmts/bsb/Makefile.dist
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
bsb2raw:
|
||||
$(CXX) $(CFLAGS) *.c *.cpp -o bsb2raw
|
||||
48
bazaar/plugin/gdal/frmts/bsb/README.dist
Normal file
48
bazaar/plugin/gdal/frmts/bsb/README.dist
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
Sample BSB Reader
|
||||
=================
|
||||
|
||||
|
||||
Files
|
||||
-----
|
||||
|
||||
bsb2raw.c: Sample mainline program for converting BSB files to "raw" format.
|
||||
|
||||
bsb_read.c: Core BSB reading code ... you may use this in your application.
|
||||
bsb_read.h: Declarations for functions and structures in bsb_read.c. #include
|
||||
this from your application.
|
||||
|
||||
cpl_*: Supporting low level code and include files.
|
||||
|
||||
Makefile: Simple Unix style makefile for building bsb2raw program.
|
||||
|
||||
NOTE: It may be necessary to fool with the cpl_config.h include file for
|
||||
different platforms. In particular, change the #undef WORDS_BIGENDIAN to
|
||||
a #define WORDS_BIGENDIAN for big endian systems (Sparc, SGI, etc). Some
|
||||
changes may be needed in cpl_config.h for Windows.
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
MIT/X license ... see header of bsb_read.c.
|
||||
|
||||
On the Web
|
||||
----------
|
||||
|
||||
http://gdal.velocet.ca/projects/bsb/
|
||||
|
||||
GDAL
|
||||
----
|
||||
|
||||
Note that this BSB code is normally incorporated into the larger GDAL
|
||||
library. To convert BSB to other common formats like GeoTIFF, PNG, etc
|
||||
consider using the GDAL utilities at:
|
||||
|
||||
http://www.remotesensing.org/gdal
|
||||
|
||||
|
||||
July 19, 2002
|
||||
Frank Warmerdam <warmerdam@pobox.com>
|
||||
|
||||
|
||||
|
||||
109
bazaar/plugin/gdal/frmts/bsb/bsb2raw.c
Normal file
109
bazaar/plugin/gdal/frmts/bsb/bsb2raw.c
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/******************************************************************************
|
||||
* $Id: bsb2raw.c 10645 2007-01-18 02:22:39Z warmerdam $
|
||||
*
|
||||
* Project: BSB Reader
|
||||
* Purpose: Test program for dumping BSB to PPM raster format.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2001, Frank Warmerdam
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "cpl_error.h"
|
||||
#include "cpl_vsi.h"
|
||||
#include "cpl_conv.h"
|
||||
#include "bsb_read.h"
|
||||
|
||||
CPL_CVSID("$Id: bsb2raw.c 10645 2007-01-18 02:22:39Z warmerdam $");
|
||||
|
||||
/************************************************************************/
|
||||
/* main() */
|
||||
/************************************************************************/
|
||||
|
||||
int main( int nArgc, char **papszArgv )
|
||||
|
||||
{
|
||||
BSBInfo *psInfo;
|
||||
int iLine, i;
|
||||
GByte *pabyScanline;
|
||||
FILE *fp;
|
||||
int nError = 0;
|
||||
|
||||
if( nArgc < 3 )
|
||||
{
|
||||
fprintf( stderr, "Usage: bsb2raw src_file dst_file\n" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
psInfo = BSBOpen( papszArgv[1] );
|
||||
if( psInfo == NULL )
|
||||
exit( 1 );
|
||||
|
||||
fp = VSIFOpen( papszArgv[2], "wb" );
|
||||
if( fp == NULL )
|
||||
{
|
||||
perror( "open" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
pabyScanline = (GByte *) CPLMalloc(psInfo->nXSize);
|
||||
for( iLine = 0; iLine < psInfo->nYSize; iLine++ )
|
||||
{
|
||||
if( !BSBReadScanline( psInfo, iLine, pabyScanline ) )
|
||||
nError++;
|
||||
|
||||
VSIFWrite( pabyScanline, 1, psInfo->nXSize, fp );
|
||||
}
|
||||
|
||||
VSIFClose( fp );
|
||||
|
||||
if( nError > 0 )
|
||||
fprintf( stderr, "Read failed for %d scanlines out of %d.\n",
|
||||
nError, psInfo->nYSize );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Write .aux file. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
fp = VSIFOpen( CPLResetExtension( papszArgv[2], "aux" ), "wt" );
|
||||
|
||||
fprintf( fp, "AuxilaryTarget: %s\n",
|
||||
CPLGetFilename(papszArgv[2]) );
|
||||
|
||||
fprintf( fp, "RawDefinition: %d %d 1\n",
|
||||
psInfo->nXSize, psInfo->nYSize );
|
||||
|
||||
fprintf( fp, "ChanDefinition-1: 8U 0 1 %d Swapped\n",
|
||||
psInfo->nXSize );
|
||||
|
||||
for( i = 0; i < psInfo->nPCTSize; i++ )
|
||||
fprintf( fp, "METADATA_IMG_1_Class_%d_Color: (RGB:%d %d %d)\n",
|
||||
i,
|
||||
psInfo->pabyPCT[i*3 + 0],
|
||||
psInfo->pabyPCT[i*3 + 1],
|
||||
psInfo->pabyPCT[i*3 + 2] );
|
||||
|
||||
VSIFClose( fp );
|
||||
|
||||
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
|
||||
1080
bazaar/plugin/gdal/frmts/bsb/bsb_read.c
Normal file
1080
bazaar/plugin/gdal/frmts/bsb/bsb_read.c
Normal file
File diff suppressed because it is too large
Load diff
83
bazaar/plugin/gdal/frmts/bsb/bsb_read.h
Normal file
83
bazaar/plugin/gdal/frmts/bsb/bsb_read.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/******************************************************************************
|
||||
* $Id: bsb_read.h 20996 2010-10-28 18:38:15Z rouault $
|
||||
*
|
||||
* Project: BSB Reader
|
||||
* Purpose: non-GDAL BSB API Declarations
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2001, Frank Warmerdam
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _BSBREAD_H_INCLUDED
|
||||
#define _BSBREAD_H_INCLUDED
|
||||
|
||||
#include "cpl_port.h"
|
||||
#include "cpl_vsi.h"
|
||||
|
||||
CPL_C_START
|
||||
|
||||
typedef struct {
|
||||
VSILFILE *fp;
|
||||
|
||||
|
||||
GByte *pabyBuffer;
|
||||
int nBufferOffset;
|
||||
int nBufferSize;
|
||||
int nBufferAllocation;
|
||||
int nSavedCharacter;
|
||||
|
||||
int nXSize;
|
||||
int nYSize;
|
||||
|
||||
int nPCTSize;
|
||||
unsigned char *pabyPCT;
|
||||
|
||||
char **papszHeader;
|
||||
|
||||
int *panLineOffset;
|
||||
|
||||
int nColorSize;
|
||||
|
||||
int nVersion; /* times 100 */
|
||||
|
||||
int bNO1;
|
||||
|
||||
int bNewFile;
|
||||
int nLastLineWritten;
|
||||
} BSBInfo;
|
||||
|
||||
BSBInfo CPL_DLL *BSBOpen( const char *pszFilename );
|
||||
int CPL_DLL BSBReadScanline( BSBInfo *psInfo, int nScanline,
|
||||
unsigned char *pabyScanlineBuf );
|
||||
void CPL_DLL BSBClose( BSBInfo *psInfo );
|
||||
|
||||
BSBInfo CPL_DLL *BSBCreate( const char *pszFilename, int nCreationFlags,
|
||||
int nVersion, int nXSize, int nYSize );
|
||||
int CPL_DLL BSBWritePCT( BSBInfo *psInfo,
|
||||
int nPCTSize, unsigned char *pabyPCT );
|
||||
int CPL_DLL BSBWriteScanline( BSBInfo *psInfo,
|
||||
unsigned char *pabyScanlineBuf );
|
||||
|
||||
CPL_C_END
|
||||
|
||||
|
||||
#endif /* ndef _BSBREAD_H_INCLUDED */
|
||||
1207
bazaar/plugin/gdal/frmts/bsb/bsbdataset.cpp
Normal file
1207
bazaar/plugin/gdal/frmts/bsb/bsbdataset.cpp
Normal file
File diff suppressed because it is too large
Load diff
13
bazaar/plugin/gdal/frmts/bsb/makefile.vc
Normal file
13
bazaar/plugin/gdal/frmts/bsb/makefile.vc
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
OBJ = bsbdataset.obj bsb_read.obj
|
||||
|
||||
GDAL_ROOT = ..\..
|
||||
|
||||
!INCLUDE $(GDAL_ROOT)\nmake.opt
|
||||
|
||||
default: $(OBJ)
|
||||
xcopy /D /Y *.obj ..\o
|
||||
|
||||
clean:
|
||||
-del *.obj
|
||||
|
||||
17
bazaar/plugin/gdal/frmts/ceos/GNUmakefile
Normal file
17
bazaar/plugin/gdal/frmts/ceos/GNUmakefile
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
|
||||
include ../../GDALmake.opt
|
||||
|
||||
OBJ = ceosopen.o ceosdataset.o
|
||||
|
||||
|
||||
|
||||
default: $(OBJ:.o=.$(OBJ_EXT))
|
||||
|
||||
clean:
|
||||
rm -f *.o $(O_OBJ)
|
||||
|
||||
ceostest$(EXE): ceostest.$(OBJ_EXT)
|
||||
$(LD) $(LDFLAGS) ceostest.$(OBJ_EXT) $(CONFIG_LIBS) -o ceostest$(EXE)
|
||||
|
||||
install-obj: $(O_OBJ:.o=.$(OBJ_EXT))
|
||||
257
bazaar/plugin/gdal/frmts/ceos/ceosdataset.cpp
Normal file
257
bazaar/plugin/gdal/frmts/ceos/ceosdataset.cpp
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
/******************************************************************************
|
||||
* $Id: ceosdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
|
||||
*
|
||||
* Project: CEOS Translator
|
||||
* Purpose: GDALDataset driver for CEOS translator.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 1999, Frank Warmerdam
|
||||
* Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "ceosopen.h"
|
||||
#include "gdal_pam.h"
|
||||
|
||||
CPL_CVSID("$Id: ceosdataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
|
||||
|
||||
CPL_C_START
|
||||
void GDALRegister_CEOS(void);
|
||||
CPL_C_END
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* CEOSDataset */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
class CEOSRasterBand;
|
||||
|
||||
class CEOSDataset : public GDALPamDataset
|
||||
{
|
||||
friend class CEOSRasterBand;
|
||||
|
||||
CEOSImage *psCEOS;
|
||||
|
||||
public:
|
||||
CEOSDataset();
|
||||
~CEOSDataset();
|
||||
static GDALDataset *Open( GDALOpenInfo * );
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* CEOSRasterBand */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
class CEOSRasterBand : public GDALPamRasterBand
|
||||
{
|
||||
friend class CEOSDataset;
|
||||
|
||||
public:
|
||||
|
||||
CEOSRasterBand( CEOSDataset *, int );
|
||||
|
||||
virtual CPLErr IReadBlock( int, int, void * );
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* CEOSRasterBand() */
|
||||
/************************************************************************/
|
||||
|
||||
CEOSRasterBand::CEOSRasterBand( CEOSDataset *poDS, int nBand )
|
||||
|
||||
{
|
||||
this->poDS = poDS;
|
||||
this->nBand = nBand;
|
||||
|
||||
eDataType = GDT_Byte;
|
||||
|
||||
nBlockXSize = poDS->GetRasterXSize();
|
||||
nBlockYSize = 1;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* IReadBlock() */
|
||||
/************************************************************************/
|
||||
|
||||
CPLErr CEOSRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
|
||||
int nBlockYOff,
|
||||
void * pImage )
|
||||
{
|
||||
CEOSDataset *poCEOS_DS = (CEOSDataset *) poDS;
|
||||
|
||||
CPLAssert( nBlockXOff == 0 );
|
||||
|
||||
return( CEOSReadScanline(poCEOS_DS->psCEOS, nBand, nBlockYOff+1, pImage) );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ==================================================================== */
|
||||
/* CEOSDataset */
|
||||
/* ==================================================================== */
|
||||
/************************************************************************/
|
||||
|
||||
/************************************************************************/
|
||||
/* CEOSDataset() */
|
||||
/************************************************************************/
|
||||
|
||||
CEOSDataset::CEOSDataset()
|
||||
|
||||
{
|
||||
psCEOS = NULL;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ~CEOSDataset() */
|
||||
/************************************************************************/
|
||||
|
||||
CEOSDataset::~CEOSDataset()
|
||||
|
||||
{
|
||||
FlushCache();
|
||||
if( psCEOS )
|
||||
CEOSClose( psCEOS );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Open() */
|
||||
/************************************************************************/
|
||||
|
||||
GDALDataset *CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
|
||||
|
||||
{
|
||||
CEOSImage *psCEOS;
|
||||
int i;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Before trying CEOSOpen() we first verify that the first */
|
||||
/* record is in fact a CEOS file descriptor record. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( poOpenInfo->nHeaderBytes < 100 )
|
||||
return NULL;
|
||||
|
||||
if( poOpenInfo->pabyHeader[4] != 0x3f
|
||||
|| poOpenInfo->pabyHeader[5] != 0xc0
|
||||
|| poOpenInfo->pabyHeader[6] != 0x12
|
||||
|| poOpenInfo->pabyHeader[7] != 0x12 )
|
||||
return NULL;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Try opening the dataset. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
psCEOS = CEOSOpen( poOpenInfo->pszFilename, "rb" );
|
||||
|
||||
if( psCEOS == NULL )
|
||||
return( NULL );
|
||||
|
||||
if( psCEOS->nBitsPerPixel != 8 )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_NotSupported,
|
||||
"The CEOS driver cannot handle nBitsPerPixel = %d",
|
||||
psCEOS->nBitsPerPixel );
|
||||
CEOSClose(psCEOS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !GDALCheckDatasetDimensions(psCEOS->nPixels, psCEOS->nBands) ||
|
||||
!GDALCheckBandCount(psCEOS->nBands, FALSE) )
|
||||
{
|
||||
CEOSClose( psCEOS );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Confirm the requested access is supported. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( poOpenInfo->eAccess == GA_Update )
|
||||
{
|
||||
CEOSClose(psCEOS);
|
||||
CPLError( CE_Failure, CPLE_NotSupported,
|
||||
"The CEOS driver does not support update access to existing"
|
||||
" datasets.\n" );
|
||||
return NULL;
|
||||
}
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create a corresponding GDALDataset. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CEOSDataset *poDS;
|
||||
|
||||
poDS = new CEOSDataset();
|
||||
|
||||
poDS->psCEOS = psCEOS;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Capture some information from the file that is of interest. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poDS->nRasterXSize = psCEOS->nPixels;
|
||||
poDS->nRasterYSize = psCEOS->nLines;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create band information objects. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poDS->nBands = psCEOS->nBands;;
|
||||
|
||||
for( i = 0; i < poDS->nBands; i++ )
|
||||
poDS->SetBand( i+1, new CEOSRasterBand( poDS, i+1 ) );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Initialize any PAM information. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poDS->SetDescription( poOpenInfo->pszFilename );
|
||||
poDS->TryLoadXML();
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Check for overviews. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
|
||||
|
||||
return( poDS );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* GDALRegister_GTiff() */
|
||||
/************************************************************************/
|
||||
|
||||
void GDALRegister_CEOS()
|
||||
|
||||
{
|
||||
GDALDriver *poDriver;
|
||||
|
||||
if( GDALGetDriverByName( "CEOS" ) == NULL )
|
||||
{
|
||||
poDriver = new GDALDriver();
|
||||
|
||||
poDriver->SetDescription( "CEOS" );
|
||||
poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
|
||||
poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
|
||||
"CEOS Image" );
|
||||
poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
|
||||
"frmt_various.html#CEOS" );
|
||||
poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
|
||||
|
||||
poDriver->pfnOpen = CEOSDataset::Open;
|
||||
|
||||
GetGDALDriverManager()->RegisterDriver( poDriver );
|
||||
}
|
||||
}
|
||||
379
bazaar/plugin/gdal/frmts/ceos/ceosopen.c
Normal file
379
bazaar/plugin/gdal/frmts/ceos/ceosopen.c
Normal file
|
|
@ -0,0 +1,379 @@
|
|||
/******************************************************************************
|
||||
* $Id: ceosopen.c 27745 2014-09-27 16:38:57Z goatbar $
|
||||
*
|
||||
* Project: CEOS Translator
|
||||
* Purpose: Implementation of non-GDAL dependent CEOS support.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 1999, Frank Warmerdam
|
||||
* Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "ceosopen.h"
|
||||
|
||||
CPL_CVSID("$Id: ceosopen.c 27745 2014-09-27 16:38:57Z goatbar $");
|
||||
|
||||
/************************************************************************/
|
||||
/* CEOSScanInt() */
|
||||
/* */
|
||||
/* Read up to nMaxChars from the passed string, and interpret */
|
||||
/* as an integer. */
|
||||
/************************************************************************/
|
||||
|
||||
static long CEOSScanInt( const char * pszString, int nMaxChars )
|
||||
|
||||
{
|
||||
char szWorking[33];
|
||||
int i;
|
||||
|
||||
if( nMaxChars > 32 || nMaxChars == 0 )
|
||||
nMaxChars = 32;
|
||||
|
||||
for( i = 0; i < nMaxChars && pszString[i] != '\0'; i++ )
|
||||
szWorking[i] = pszString[i];
|
||||
|
||||
szWorking[i] = '\0';
|
||||
|
||||
return( atoi(szWorking) );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* CEOSReadRecord() */
|
||||
/* */
|
||||
/* Read a single CEOS record at the current point in the file. */
|
||||
/* Return NULL after reporting an error if it fails, otherwise */
|
||||
/* return the record. */
|
||||
/************************************************************************/
|
||||
|
||||
CEOSRecord * CEOSReadRecord( CEOSImage *psImage )
|
||||
|
||||
{
|
||||
GByte abyHeader[12];
|
||||
CEOSRecord *psRecord;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read the standard CEOS header. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( VSIFEofL( psImage->fpImage ) )
|
||||
return NULL;
|
||||
|
||||
if( VSIFReadL( abyHeader, 1, 12, psImage->fpImage ) != 12 )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_FileIO,
|
||||
"Ran out of data reading CEOS record." );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Extract this information. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
psRecord = (CEOSRecord *) CPLMalloc(sizeof(CEOSRecord));
|
||||
if( psImage->bLittleEndian )
|
||||
{
|
||||
CPL_SWAP32PTR( abyHeader + 0 );
|
||||
CPL_SWAP32PTR( abyHeader + 8 );
|
||||
}
|
||||
|
||||
psRecord->nRecordNum = abyHeader[0] * 256 * 256 * 256
|
||||
+ abyHeader[1] * 256 * 256
|
||||
+ abyHeader[2] * 256
|
||||
+ abyHeader[3];
|
||||
|
||||
psRecord->nRecordType = abyHeader[4] * 256 * 256 * 256
|
||||
+ abyHeader[5] * 256 * 256
|
||||
+ abyHeader[6] * 256
|
||||
+ abyHeader[7];
|
||||
|
||||
psRecord->nLength = abyHeader[8] * 256 * 256 * 256
|
||||
+ abyHeader[9] * 256 * 256
|
||||
+ abyHeader[10] * 256
|
||||
+ abyHeader[11];
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Does it look reasonable? We assume there can't be too many */
|
||||
/* records and that the length must be between 12 and 200000. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( psRecord->nRecordNum < 0 || psRecord->nRecordNum > 200000
|
||||
|| psRecord->nLength < 12 || psRecord->nLength > 200000 )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"CEOS record leader appears to be corrupt.\n"
|
||||
"Record Number = %d, Record Length = %d\n",
|
||||
psRecord->nRecordNum, psRecord->nLength );
|
||||
CPLFree( psRecord );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read the remainder of the record into a buffer. Ensure that */
|
||||
/* the first 12 bytes gets moved into this buffer as well. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
psRecord->pachData = (char *) VSIMalloc(psRecord->nLength );
|
||||
if( psRecord->pachData == NULL )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_OutOfMemory,
|
||||
"Out of memory allocated %d bytes for CEOS record data.\n"
|
||||
"Are you sure you aren't leaking CEOSRecords?\n",
|
||||
psRecord->nLength );
|
||||
CPLFree( psRecord );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy( psRecord->pachData, abyHeader, 12 );
|
||||
|
||||
if( (int)VSIFReadL( psRecord->pachData + 12, 1, psRecord->nLength-12,
|
||||
psImage->fpImage )
|
||||
!= psRecord->nLength - 12 )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_FileIO,
|
||||
"Short read on CEOS record data.\n" );
|
||||
CPLFree( psRecord );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return psRecord;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* CEOSDestroyRecord() */
|
||||
/* */
|
||||
/* Free a record. */
|
||||
/************************************************************************/
|
||||
|
||||
void CEOSDestroyRecord( CEOSRecord * psRecord )
|
||||
|
||||
{
|
||||
CPLFree( psRecord->pachData );
|
||||
CPLFree( psRecord );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* CEOSOpen() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Open a CEOS transfer.
|
||||
*
|
||||
* @param pszFilename The name of the CEOS imagery file (ie. imag_01.dat).
|
||||
* @param pszAccess An fopen() style access string. Should be either "rb" for
|
||||
* read-only access, or "r+b" for read, and update access.
|
||||
*
|
||||
* @return A CEOSImage pointer as a handle to the image. The CEOSImage also
|
||||
* has various information about the image available. A NULL is returned
|
||||
* if an error occurs.
|
||||
*/
|
||||
|
||||
CEOSImage * CEOSOpen( const char * pszFilename, const char * pszAccess )
|
||||
|
||||
{
|
||||
VSILFILE *fp;
|
||||
CEOSRecord *psRecord;
|
||||
CEOSImage *psImage;
|
||||
int nSeqNum, i;
|
||||
GByte abyHeader[16];
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Try to open the imagery file. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
fp = VSIFOpenL( pszFilename, pszAccess );
|
||||
|
||||
if( fp == NULL )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_OpenFailed,
|
||||
"Failed to open CEOS file `%s' with access `%s'.\n",
|
||||
pszFilename, pszAccess );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create a CEOSImage structure, and initialize it. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
psImage = (CEOSImage *) CPLCalloc(1,sizeof(CEOSImage));
|
||||
psImage->fpImage = fp;
|
||||
|
||||
psImage->nPixels = psImage->nLines = psImage->nBands = 0;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Preread info on the first record, to establish if it is */
|
||||
/* little endian. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
VSIFReadL( abyHeader, 16, 1, fp );
|
||||
VSIFSeekL( fp, 0, SEEK_SET );
|
||||
|
||||
if( abyHeader[0] != 0 || abyHeader[1] != 0 )
|
||||
psImage->bLittleEndian = TRUE;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Try to read the header record. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
psRecord = CEOSReadRecord( psImage );
|
||||
if( psRecord == NULL )
|
||||
{
|
||||
CEOSClose( psImage );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( psRecord->nRecordType != CRT_IMAGE_FDR )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_AppDefined,
|
||||
"Got a %X type record, instead of the expected\n"
|
||||
"file descriptor record on file %s.\n",
|
||||
psRecord->nRecordType, pszFilename );
|
||||
|
||||
CEOSDestroyRecord( psRecord );
|
||||
CEOSClose( psImage );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* The sequence number should be 2 indicating this is the */
|
||||
/* imagery file. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
nSeqNum = CEOSScanInt( psRecord->pachData + 44, 4 );
|
||||
if( nSeqNum != 2 )
|
||||
{
|
||||
CPLError( CE_Warning, CPLE_AppDefined,
|
||||
"Got a %d file sequence number, instead of the expected\n"
|
||||
"2 indicating imagery on file %s.\n"
|
||||
"Continuing to access anyways.\n",
|
||||
nSeqNum, pszFilename );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Extract various information. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
psImage->nImageRecCount = CEOSScanInt( psRecord->pachData+180, 6 );
|
||||
psImage->nImageRecLength = CEOSScanInt( psRecord->pachData+186, 6 );
|
||||
psImage->nBitsPerPixel = CEOSScanInt( psRecord->pachData+216, 4 );
|
||||
psImage->nBands = CEOSScanInt( psRecord->pachData+232, 4 );
|
||||
psImage->nLines = CEOSScanInt( psRecord->pachData+236, 8 );
|
||||
psImage->nPixels = CEOSScanInt( psRecord->pachData+248, 8 );
|
||||
|
||||
psImage->nPrefixBytes = CEOSScanInt( psRecord->pachData+276, 4 );
|
||||
psImage->nSuffixBytes = CEOSScanInt( psRecord->pachData+288, 4 );
|
||||
|
||||
|
||||
if( psImage->nImageRecLength <= 0 ||
|
||||
psImage->nPrefixBytes < 0 ||
|
||||
psImage->nBands > INT_MAX / psImage->nImageRecLength ||
|
||||
(size_t)psImage->nBands > INT_MAX / sizeof(int))
|
||||
{
|
||||
CEOSDestroyRecord( psRecord );
|
||||
CEOSClose( psImage );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Try to establish the layout of the imagery data. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
psImage->nLineOffset = psImage->nBands * psImage->nImageRecLength;
|
||||
|
||||
psImage->panDataStart = (int *) VSIMalloc(sizeof(int) * psImage->nBands);
|
||||
if( psImage->panDataStart == NULL )
|
||||
{
|
||||
CEOSDestroyRecord( psRecord );
|
||||
CEOSClose( psImage );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( i = 0; i < psImage->nBands; i++ )
|
||||
{
|
||||
psImage->panDataStart[i] =
|
||||
psRecord->nLength + i * psImage->nImageRecLength
|
||||
+ 12 + psImage->nPrefixBytes;
|
||||
}
|
||||
|
||||
CEOSDestroyRecord( psRecord );
|
||||
|
||||
return psImage;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* CEOSReadScanline() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Read a scanline of image.
|
||||
*
|
||||
* @param psCEOS The CEOS dataset handle returned by CEOSOpen().
|
||||
* @param nBand The band number (ie. 1, 2, 3).
|
||||
* @param nScanline The scanline requested, one based.
|
||||
* @param pData The data buffer to read into. Must be at least nPixels *
|
||||
* nBitesPerPixel bits long.
|
||||
*
|
||||
* @return CPLErr Returns error indicator or CE_None if the read succeeds.
|
||||
*/
|
||||
|
||||
CPLErr CEOSReadScanline( CEOSImage * psCEOS, int nBand, int nScanline,
|
||||
void * pData )
|
||||
|
||||
{
|
||||
int nOffset, nBytes;
|
||||
|
||||
/*
|
||||
* As a short cut, I currently just seek to the data, and read it
|
||||
* raw, rather than trying to read ceos records properly.
|
||||
*/
|
||||
|
||||
nOffset = psCEOS->panDataStart[nBand-1]
|
||||
+ (nScanline-1) * psCEOS->nLineOffset;
|
||||
|
||||
if( VSIFSeekL( psCEOS->fpImage, nOffset, SEEK_SET ) != 0 )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_FileIO,
|
||||
"Seek to %d for scanline %d failed.\n",
|
||||
nOffset, nScanline );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read the data. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
nBytes = psCEOS->nPixels * psCEOS->nBitsPerPixel / 8;
|
||||
if( (int) VSIFReadL( pData, 1, nBytes, psCEOS->fpImage ) != nBytes )
|
||||
{
|
||||
CPLError( CE_Failure, CPLE_FileIO,
|
||||
"Read of %d bytes for scanline %d failed.\n",
|
||||
nBytes, nScanline );
|
||||
return CE_Failure;
|
||||
}
|
||||
|
||||
return CE_None;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* CEOSClose() */
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* Close a CEOS transfer. Any open files are closed, and memory deallocated.
|
||||
*
|
||||
* @param psCEOS The CEOSImage handle from CEOSOpen to be closed.
|
||||
*/
|
||||
|
||||
void CEOSClose( CEOSImage * psCEOS )
|
||||
|
||||
{
|
||||
CPLFree( psCEOS->panDataStart );
|
||||
VSIFCloseL( psCEOS->fpImage );
|
||||
CPLFree( psCEOS );
|
||||
}
|
||||
108
bazaar/plugin/gdal/frmts/ceos/ceosopen.h
Normal file
108
bazaar/plugin/gdal/frmts/ceos/ceosopen.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
/******************************************************************************
|
||||
* $Id: ceosopen.h 20996 2010-10-28 18:38:15Z rouault $
|
||||
*
|
||||
* Project: CEOS Translator
|
||||
* Purpose: Public (C callable) interface for CEOS and related formats such
|
||||
* as Spot CAP. This stuff can be used independently of GDAL.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 1999, Frank Warmerdam
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _CEOSOPEN_H_INCLUDED
|
||||
#define _CEOSOPEN_H_INCLUDED
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Include standard portability stuff. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
#include "cpl_conv.h"
|
||||
#include "cpl_string.h"
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Base ``class'' for ceos records. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
CPL_C_START
|
||||
|
||||
typedef struct {
|
||||
int nRecordNum;
|
||||
GUInt32 nRecordType;
|
||||
int nLength;
|
||||
|
||||
char *pachData;
|
||||
}CEOSRecord;
|
||||
|
||||
/* well known record types */
|
||||
#define CRT_IMAGE_FDR 0x3FC01212
|
||||
#define CRT_IMAGE_DATA 0xEDED1212
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Main CEOS info structure. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* public information */
|
||||
int nPixels;
|
||||
int nLines;
|
||||
int nBands;
|
||||
|
||||
int nBitsPerPixel;
|
||||
|
||||
/* private information */
|
||||
VSILFILE *fpImage;
|
||||
|
||||
int bLittleEndian;
|
||||
|
||||
int nImageRecCount;
|
||||
int nImageRecLength;
|
||||
|
||||
int nPrefixBytes;
|
||||
int nSuffixBytes;
|
||||
|
||||
int *panDataStart;
|
||||
int nLineOffset;
|
||||
|
||||
} CEOSImage;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* External Prototypes */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
CEOSImage CPL_ODLL *CEOSOpen( const char *, const char * );
|
||||
void CPL_ODLL CEOSClose( CEOSImage * );
|
||||
CPLErr CPL_ODLL CEOSReadScanline( CEOSImage *psImage, int nBand,
|
||||
int nScanline, void * pData );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Internal prototypes. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CEOSRecord CPL_ODLL *CEOSReadRecord( CEOSImage * );
|
||||
void CPL_ODLL CEOSDestroyRecord( CEOSRecord * );
|
||||
|
||||
CPL_C_END
|
||||
|
||||
#endif /* ndef _CEOSOPEN_H_INCLUDED */
|
||||
|
||||
|
||||
|
||||
69
bazaar/plugin/gdal/frmts/ceos/ceostest.c
Normal file
69
bazaar/plugin/gdal/frmts/ceos/ceostest.c
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/******************************************************************************
|
||||
* $Id: ceostest.c 20504 2010-09-02 02:40:49Z warmerdam $
|
||||
*
|
||||
* Project: CEOS Translator
|
||||
* Purpose: Test mainline.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 1999, Frank Warmerdam
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "ceosopen.h"
|
||||
|
||||
/************************************************************************/
|
||||
/* main() */
|
||||
/************************************************************************/
|
||||
|
||||
int main( int nArgc, char ** papszArgv )
|
||||
|
||||
{
|
||||
const char *pszFilename;
|
||||
FILE *fp;
|
||||
CEOSRecord *psRecord;
|
||||
int nPosition = 0;
|
||||
|
||||
if( nArgc > 1 )
|
||||
pszFilename = papszArgv[1];
|
||||
else
|
||||
pszFilename = "imag_01.dat";
|
||||
|
||||
fp = VSIFOpenL( pszFilename, "rb" );
|
||||
if( fp == NULL )
|
||||
{
|
||||
fprintf( stderr, "Can't open %s at all.\n", pszFilename );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
while( !VSIFEofL(fp)
|
||||
&& (psRecord = CEOSReadRecord( fp )) != NULL )
|
||||
{
|
||||
printf( "%9d:%4d:%8x:%d\n",
|
||||
nPosition, psRecord->nRecordNum,
|
||||
psRecord->nRecordType, psRecord->nLength );
|
||||
CEOSDestroyRecord( psRecord );
|
||||
|
||||
nPosition = (int) VSIFTellL( fp );
|
||||
}
|
||||
VSIFCloseL( fp );
|
||||
|
||||
exit( 0 );
|
||||
}
|
||||
13
bazaar/plugin/gdal/frmts/ceos/makefile.vc
Normal file
13
bazaar/plugin/gdal/frmts/ceos/makefile.vc
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
OBJ = ceosopen.obj ceosdataset.obj
|
||||
|
||||
GDAL_ROOT = ..\..
|
||||
|
||||
!INCLUDE $(GDAL_ROOT)\nmake.opt
|
||||
|
||||
default: $(OBJ)
|
||||
xcopy /D /Y *.obj ..\o
|
||||
|
||||
clean:
|
||||
-del *.obj
|
||||
|
||||
18
bazaar/plugin/gdal/frmts/ceos2/GNUmakefile
Normal file
18
bazaar/plugin/gdal/frmts/ceos2/GNUmakefile
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
|
||||
OBJ = sar_ceosdataset.o \
|
||||
ceosrecipe.o ceossar.o ceos.o link.o
|
||||
|
||||
include ../../GDALmake.opt
|
||||
|
||||
|
||||
CPPFLAGS := -I../raw $(CPPFLAGS)
|
||||
|
||||
default: $(OBJ:.o=.$(OBJ_EXT))
|
||||
|
||||
$(O_OBJ): ../raw/rawdataset.h
|
||||
|
||||
clean:
|
||||
rm -f *.o $(O_OBJ)
|
||||
|
||||
install-obj: $(O_OBJ:.o=.$(OBJ_EXT))
|
||||
408
bazaar/plugin/gdal/frmts/ceos2/ceos.c
Normal file
408
bazaar/plugin/gdal/frmts/ceos2/ceos.c
Normal file
|
|
@ -0,0 +1,408 @@
|
|||
/******************************************************************************
|
||||
* $Id: ceos.c 20996 2010-10-28 18:38:15Z rouault $
|
||||
*
|
||||
* Project: ASI CEOS Translator
|
||||
* Purpose: Core CEOS functions.
|
||||
* Author: Paul Lahaie, pjlahaie@atlsci.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2000, Atlantis Scientific Inc
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "ceos.h"
|
||||
|
||||
CPL_CVSID("$Id: ceos.c 20996 2010-10-28 18:38:15Z rouault $");
|
||||
|
||||
/* Function implementations of functions described in ceos.h */
|
||||
|
||||
void CeosUpdateHeaderFromBuffer(CeosRecord_t *record);
|
||||
|
||||
void InitEmptyCeosRecord(CeosRecord_t *record, int32 sequence, CeosTypeCode_t typecode, int32 length)
|
||||
{
|
||||
if(record)
|
||||
{
|
||||
if((record->Buffer = HMalloc(length)) == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* First we zero fill the buffer */
|
||||
memset(record->Buffer,0,length);
|
||||
|
||||
/* Setup values inside the CeosRecord_t header */
|
||||
record->Sequence = sequence;
|
||||
record->Flavour = 0;
|
||||
record->FileId = 0;
|
||||
record->TypeCode = typecode;
|
||||
record->Subsequence = 0;
|
||||
record->Length = length;
|
||||
|
||||
/* Now we fill in the buffer portion as well */
|
||||
NativeToCeos( record->Buffer+__SEQUENCE_OFF, &(record->Sequence), sizeof(record->Sequence), sizeof( record->Sequence ) );
|
||||
memcpy(record->Buffer+__TYPE_OFF, &( record->TypeCode.Int32Code ), sizeof( record->TypeCode.Int32Code ) );
|
||||
NativeToCeos( record->Buffer+__LENGTH_OFF, &length, sizeof( length ), sizeof( length ) );
|
||||
}
|
||||
}
|
||||
|
||||
void InitCeosRecord(CeosRecord_t *record, uchar *buffer)
|
||||
{
|
||||
if(record && buffer)
|
||||
{
|
||||
InitCeosRecordWithHeader(record, buffer, buffer+__CEOS_HEADER_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
void InitCeosRecordWithHeader(CeosRecord_t *record, uchar *header, uchar *buffer)
|
||||
{
|
||||
if(record && buffer && header)
|
||||
{
|
||||
if( record->Length != 0 )
|
||||
record->Length = DetermineCeosRecordBodyLength( header );
|
||||
|
||||
if((record->Buffer = HMalloc(record->Length)) == NULL)
|
||||
{
|
||||
record->Length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* First copy the header then the buffer */
|
||||
memcpy(record->Buffer,header,__CEOS_HEADER_LENGTH);
|
||||
/* Now we copy the rest */
|
||||
memcpy(record->Buffer+__CEOS_HEADER_LENGTH,buffer,record->Length-__CEOS_HEADER_LENGTH);
|
||||
|
||||
/* Now we fill in the rest of the structure! */
|
||||
memcpy(&(record->TypeCode.Int32Code),header+__TYPE_OFF,sizeof(record->TypeCode.Int32Code));
|
||||
CeosToNative(&(record->Sequence),header+__SEQUENCE_OFF,sizeof(record->Sequence), sizeof( record->Sequence ) );
|
||||
}
|
||||
}
|
||||
|
||||
int DetermineCeosRecordBodyLength(const uchar *header)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(header)
|
||||
{
|
||||
CeosToNative(&i,header+__LENGTH_OFF,sizeof( i ), sizeof( i ) );
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void DeleteCeosRecord(CeosRecord_t *record)
|
||||
{
|
||||
if(record)
|
||||
{
|
||||
if(record->Buffer)
|
||||
{
|
||||
HFree(record->Buffer);
|
||||
record->Buffer = NULL;
|
||||
}
|
||||
HFree( record );
|
||||
}
|
||||
}
|
||||
|
||||
void GetCeosRecordStruct(const CeosRecord_t *record,void *struct_ptr)
|
||||
{
|
||||
if(record && struct_ptr && record->Buffer)
|
||||
{
|
||||
memcpy(record->Buffer,struct_ptr,record->Length);
|
||||
}
|
||||
}
|
||||
|
||||
void PutCeosRecordStruct(CeosRecord_t *record,const void *struct_ptr)
|
||||
{
|
||||
int Length;
|
||||
|
||||
if(record && struct_ptr)
|
||||
{
|
||||
CeosToNative( &Length, struct_ptr, sizeof( Length ), sizeof( Length ) );
|
||||
memcpy(record->Buffer,struct_ptr,Length);
|
||||
CeosUpdateHeaderFromBuffer(record);
|
||||
}
|
||||
}
|
||||
|
||||
void GetCeosField(CeosRecord_t *record, int32 start_byte,
|
||||
const char *format, void *value)
|
||||
{
|
||||
int field_size;
|
||||
char *d_ptr;
|
||||
char *mod_buf = NULL;
|
||||
|
||||
field_size = atoi(format+1);
|
||||
|
||||
if(field_size < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for out of bounds */
|
||||
if(start_byte + field_size - 1 > record->Length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if((mod_buf = (char *) HMalloc(field_size + 1)) == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(mod_buf,record->Buffer+(start_byte-1), field_size);
|
||||
mod_buf[field_size] = '\0';
|
||||
|
||||
/* Switch on format type */
|
||||
switch(format[0])
|
||||
{
|
||||
case 'b':
|
||||
case 'B':
|
||||
/* Binary data type */
|
||||
if(field_size > 1)
|
||||
{
|
||||
CeosToNative( value, mod_buf, field_size, field_size );
|
||||
} else {
|
||||
memcpy( value, mod_buf, field_size );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
case 'I':
|
||||
/* Integer type */
|
||||
*( (int *)value) = atoi(mod_buf);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'e':
|
||||
case 'E':
|
||||
/* Double precision float data type */
|
||||
|
||||
/* Change the 'D' exponent separators to 'e' */
|
||||
if( ( d_ptr = strchr(mod_buf, 'd') ) != NULL)
|
||||
{
|
||||
*d_ptr = 'e';
|
||||
}
|
||||
if( ( d_ptr = strchr(mod_buf, 'D') ) != NULL)
|
||||
{
|
||||
*d_ptr = 'e';
|
||||
}
|
||||
|
||||
*( (double *)value) = strtod(mod_buf,NULL);
|
||||
break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
/* ASCII.. We just easily extract it */
|
||||
( (char *)value)[field_size] = '\0';
|
||||
memcpy( value, mod_buf, field_size );
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unknown format */
|
||||
return;
|
||||
}
|
||||
|
||||
HFree(mod_buf);
|
||||
|
||||
}
|
||||
|
||||
void SetCeosField(CeosRecord_t *record, int32 start_byte, char *format, void *value)
|
||||
{
|
||||
int field_size;
|
||||
char * temp_buf = NULL;
|
||||
char printf_format[ 20 ];
|
||||
|
||||
field_size = 0;
|
||||
sscanf(&format[1], "%d", &field_size);
|
||||
if(field_size < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for bounds */
|
||||
if(start_byte + field_size - 1 > record->Length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make a local buffer to print into */
|
||||
if((temp_buf = (char *) HMalloc(field_size+1)) == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch(format[0])
|
||||
{
|
||||
case 'b':
|
||||
case 'B':
|
||||
/* Binary data type */
|
||||
if(field_size > 1)
|
||||
{
|
||||
NativeToCeos( value, temp_buf, field_size, field_size );
|
||||
} else {
|
||||
memcpy(value,temp_buf,field_size);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
case 'I':
|
||||
/* Integer data type */
|
||||
sprintf( printf_format,"%%%s%c",format+1, 'd');
|
||||
sprintf( temp_buf, printf_format, *(int *) value);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
case 'F':
|
||||
/* Double precision floating point data type */
|
||||
sprintf(printf_format, "%%%s%c", format+1, 'g');
|
||||
sprintf(temp_buf, printf_format, *(double *)value);
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
/* Double precision floating point data type (forced exponent) */
|
||||
sprintf(printf_format,"%%%s%c", format+1, 'e');
|
||||
sprintf(temp_buf, printf_format, *(double *)value);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
case 'A':
|
||||
strncpy(temp_buf,value,field_size+1);
|
||||
temp_buf[field_size] = '0';
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unknown format */
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(record->Buffer + start_byte -1, temp_buf, field_size);
|
||||
|
||||
HFree(temp_buf);
|
||||
}
|
||||
|
||||
void SetIntCeosField(CeosRecord_t *record, int32 start_byte, int32 length, int32 value)
|
||||
{
|
||||
int integer_value = value;
|
||||
char total_len[12]; /* 12 because 2^32 -> 4294967296 + I + null */
|
||||
|
||||
sprintf(total_len,"I%d",length);
|
||||
SetCeosField(record,start_byte,total_len,&integer_value);
|
||||
}
|
||||
|
||||
CeosRecord_t *FindCeosRecord(Link_t *record_list, CeosTypeCode_t typecode, int32 fileid, int32 flavour, int32 subsequence)
|
||||
{
|
||||
Link_t *Link;
|
||||
CeosRecord_t *record;
|
||||
|
||||
for( Link = record_list; Link != NULL; Link = Link->next )
|
||||
{
|
||||
record = (CeosRecord_t *)Link->object;
|
||||
|
||||
if( (record->TypeCode.Int32Code == typecode.Int32Code)
|
||||
&& ( ( fileid == -1 ) || ( record->FileId == fileid ) )
|
||||
&& ( ( flavour == -1 ) || ( record->Flavour == flavour ) )
|
||||
&& ( ( subsequence == -1 ) || ( record->Subsequence == subsequence ) ) )
|
||||
return record;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SerializeCeosRecordsToFile(Link_t *record_list, VSILFILE *fp)
|
||||
{
|
||||
Link_t *list;
|
||||
CeosRecord_t crec;
|
||||
unsigned char *Buffer;
|
||||
|
||||
list = record_list;
|
||||
|
||||
while(list != NULL)
|
||||
{
|
||||
memcpy(&crec,list->object,sizeof(CeosRecord_t));
|
||||
Buffer = crec.Buffer;
|
||||
crec.Buffer = NULL;
|
||||
VSIFWriteL(&crec,sizeof(CeosRecord_t),1,fp);
|
||||
VSIFWriteL(Buffer,crec.Length,1,fp);
|
||||
}
|
||||
}
|
||||
|
||||
void SerializeCeosRecordsFromFile(Link_t *record_list, VSILFILE *fp)
|
||||
{
|
||||
CeosRecord_t *crec;
|
||||
Link_t *Link;
|
||||
|
||||
while(!VSIFEofL(fp))
|
||||
{
|
||||
crec = HMalloc(sizeof(CeosRecord_t));
|
||||
VSIFReadL(crec,sizeof(CeosRecord_t),1,fp);
|
||||
crec->Buffer = HMalloc(crec->Length * sizeof(char) );
|
||||
VSIFReadL(crec->Buffer,sizeof(char),crec->Length,fp);
|
||||
Link = ceos2CreateLink(crec);
|
||||
AddLink(record_list,Link);
|
||||
}
|
||||
}
|
||||
|
||||
void CeosUpdateHeaderFromBuffer(CeosRecord_t *record)
|
||||
{
|
||||
if(record && record->Buffer)
|
||||
{
|
||||
CeosToNative( &( record->Length ), record->Buffer+__LENGTH_OFF, sizeof(record->Length ), sizeof( record->Length ) );
|
||||
memcpy(&(record->TypeCode.Int32Code),record->Buffer+__TYPE_OFF,sizeof(record->TypeCode.Int32Code));
|
||||
CeosToNative(&(record->Sequence),record->Buffer+__SEQUENCE_OFF,sizeof(record->Sequence ), sizeof( record->Sequence ) );
|
||||
}
|
||||
record->Subsequence = 0;
|
||||
}
|
||||
|
||||
#ifdef CPL_LSB
|
||||
|
||||
void swapbyte(void *dst,void *src,int toswap)
|
||||
{
|
||||
int i,e;
|
||||
unsigned char *in = (unsigned char *) src;
|
||||
unsigned char *out = (unsigned char *) dst;
|
||||
|
||||
for(i = 0,e=toswap;i < toswap;i++,e--)
|
||||
{
|
||||
out[i] = in[e-1];
|
||||
}
|
||||
}
|
||||
|
||||
void NativeToCeos( void *dst, const void *src, const size_t len, const size_t swapunit)
|
||||
{
|
||||
int i;
|
||||
int remainder;
|
||||
int units;
|
||||
|
||||
|
||||
remainder = len % swapunit;
|
||||
|
||||
units = len - remainder;
|
||||
|
||||
for(i = 0;i < units; i += swapunit )
|
||||
{
|
||||
swapbyte( ( unsigned char *) dst + i, ( unsigned char * ) src + i, swapunit);
|
||||
}
|
||||
|
||||
if(remainder)
|
||||
{
|
||||
memcpy( ( unsigned char * ) dst + i, ( unsigned char * ) src + i, remainder );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
332
bazaar/plugin/gdal/frmts/ceos2/ceos.h
Normal file
332
bazaar/plugin/gdal/frmts/ceos2/ceos.h
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
/******************************************************************************
|
||||
* $Id: ceos.h 20996 2010-10-28 18:38:15Z rouault $
|
||||
*
|
||||
* Project: ASI CEOS Translator
|
||||
* Purpose: CEOS library prototypes
|
||||
* Author: Paul Lahaie, pjlahaie@atlsci.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2000, Atlantis Scientific Inc
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __CEOS_H
|
||||
#define __CEOS_H
|
||||
|
||||
#include "cpl_conv.h"
|
||||
|
||||
CPL_C_START
|
||||
|
||||
#define int32 GInt32
|
||||
#define TBool int
|
||||
#define uchar unsigned char
|
||||
|
||||
typedef struct Link_t_struct
|
||||
{
|
||||
struct Link_t_struct *next;
|
||||
void *object;
|
||||
} Link_t;
|
||||
|
||||
#define HMalloc CPLMalloc
|
||||
#define HFree CPLFree
|
||||
#define HCalloc CPLCalloc
|
||||
|
||||
Link_t *ceos2CreateLink( void * pObject );
|
||||
Link_t *InsertLink(Link_t *psList, Link_t *psLink);
|
||||
void DestroyList( Link_t *psList );
|
||||
Link_t *AddLink( Link_t *psList, Link_t *psLink );
|
||||
|
||||
/* Basic CEOS header defs */
|
||||
|
||||
#define __SEQUENCE_OFF 0
|
||||
#define __TYPE_OFF 4
|
||||
#define __LENGTH_OFF 8
|
||||
#define __CEOS_HEADER_LENGTH 12
|
||||
|
||||
/* Defines for CEOS banding type */
|
||||
|
||||
#define __CEOS_IL_PIXEL 1
|
||||
#define __CEOS_IL_LINE 2
|
||||
#define __CEOS_IL_BAND 3
|
||||
|
||||
/* Defines for CEOS data types */
|
||||
|
||||
#define __CEOS_TYP_CHAR 1
|
||||
#define __CEOS_TYP_UCHAR 2
|
||||
#define __CEOS_TYP_SHORT 3
|
||||
#define __CEOS_TYP_USHORT 4
|
||||
#define __CEOS_TYP_LONG 5
|
||||
#define __CEOS_TYP_ULONG 6
|
||||
#define __CEOS_TYP_FLOAT 7
|
||||
#define __CEOS_TYP_DOUBLE 8
|
||||
#define __CEOS_TYP_COMPLEX_CHAR 9
|
||||
#define __CEOS_TYP_COMPLEX_UCHAR 10
|
||||
#define __CEOS_TYP_COMPLEX_SHORT 11
|
||||
#define __CEOS_TYP_COMPLEX_USHORT 12
|
||||
#define __CEOS_TYP_COMPLEX_LONG 13
|
||||
#define __CEOS_TYP_COMPLEX_ULONG 14
|
||||
#define __CEOS_TYP_COMPLEX_FLOAT 15
|
||||
#define __CEOS_TYP_CCP_COMPLEX_FLOAT 16 /* COMPRESSED CROSS PRODUCT */
|
||||
#define __CEOS_TYP_PALSAR_COMPLEX_SHORT 17 /* PALSAR - treat as COMPLEX SHORT*/
|
||||
|
||||
/* Defines for CEOS file names */
|
||||
|
||||
#define __CEOS_VOLUME_DIR_FILE 0
|
||||
#define __CEOS_LEADER_FILE 1
|
||||
#define __CEOS_IMAGRY_OPT_FILE 2
|
||||
#define __CEOS_TRAILER_FILE 3
|
||||
#define __CEOS_NULL_VOL_FILE 4
|
||||
#define __CEOS_ANY_FILE -1
|
||||
|
||||
/* Defines for Recipe values */
|
||||
|
||||
#define __CEOS_REC_NUMCHANS 1
|
||||
#define __CEOS_REC_INTERLEAVE 2
|
||||
#define __CEOS_REC_DATATYPE 3
|
||||
#define __CEOS_REC_BPR 4
|
||||
#define __CEOS_REC_LINES 5
|
||||
#define __CEOS_REC_TBP 6
|
||||
#define __CEOS_REC_BBP 7
|
||||
#define __CEOS_REC_PPL 8
|
||||
#define __CEOS_REC_LBP 9
|
||||
#define __CEOS_REC_RBP 10
|
||||
#define __CEOS_REC_BPP 11
|
||||
#define __CEOS_REC_RPL 12
|
||||
#define __CEOS_REC_PPR 13
|
||||
#define __CEOS_REC_IDS 14
|
||||
#define __CEOS_REC_FDL 15
|
||||
#define __CEOS_REC_PIXORD 16
|
||||
#define __CEOS_REC_LINORD 17
|
||||
#define __CEOS_REC_PRODTYPE 18
|
||||
#define __CEOS_REC_RECORDSIZE 19
|
||||
#define __CEOS_REC_SUFFIX_SIZE 20
|
||||
#define __CEOS_REC_PDBPR 21
|
||||
|
||||
/* Defines for Recipe Types */
|
||||
|
||||
#define __CEOS_REC_TYP_A 1
|
||||
#define __CEOS_REC_TYP_B 2
|
||||
#define __CEOS_REC_TYP_I 3
|
||||
|
||||
/* Defines for SAR Embedded info */
|
||||
|
||||
#define __CEOS_SAR_ACQ_YEAR 1
|
||||
#define __CEOS_SAR_ACQ_DAY 2
|
||||
#define __CEOS_SAR_ACQ_MSEC 4
|
||||
#define __CEOS_SAR_TRANS_POL 8
|
||||
#define __CEOS_SAR_PULSE_REP 16
|
||||
#define __CEOS_SAR_SLANT_FIRST 32
|
||||
#define __CEOS_SAR_SLANT_MID 64
|
||||
#define __CEOS_SAR_SLANT_LAST 128
|
||||
|
||||
/* Maximum size of LUT for Calibration records */
|
||||
#define __CEOS_RADAR_MAX_LUT 512
|
||||
#define __CEOS_RADAR_FLIP_DATE 19980101
|
||||
#define __CEOS_RADAR_FACILITY "CDPF-RSAT"
|
||||
|
||||
|
||||
typedef union
|
||||
{
|
||||
int32 Int32Code;
|
||||
struct
|
||||
{
|
||||
uchar Subtype1;
|
||||
uchar Type;
|
||||
uchar Subtype2;
|
||||
uchar Subtype3;
|
||||
} UCharCode;
|
||||
} CeosTypeCode_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32 Sequence;
|
||||
CeosTypeCode_t TypeCode;
|
||||
int32 Length;
|
||||
int32 Flavour;
|
||||
int32 Subsequence;
|
||||
int32 FileId;
|
||||
uchar * Buffer;
|
||||
} CeosRecord_t;
|
||||
|
||||
struct CeosSARImageDesc
|
||||
{
|
||||
TBool ImageDescValid;
|
||||
int NumChannels;
|
||||
int32 ChannelInterleaving;
|
||||
int32 DataType;
|
||||
int BytesPerRecord;
|
||||
int Lines;
|
||||
int TopBorderPixels;
|
||||
int BottomBorderPixels;
|
||||
int PixelsPerLine;
|
||||
int LeftBorderPixels;
|
||||
int RightBorderPixels;
|
||||
int BytesPerPixel;
|
||||
int RecordsPerLine;
|
||||
int PixelsPerRecord;
|
||||
int ImageDataStart;
|
||||
int ImageSuffixData;
|
||||
int FileDescriptorLength;
|
||||
int32 PixelOrder;
|
||||
int32 LineOrder;
|
||||
int PixelDataBytesPerRecord;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32 Flavour;
|
||||
int32 Sensor;
|
||||
int32 ProductType;
|
||||
int32 FileNamingConvention;
|
||||
TBool VolumeDirectoryFile;
|
||||
TBool SARLeaderFile;
|
||||
TBool ImagryOptionsFile;
|
||||
TBool SARTrailerFile;
|
||||
TBool NullVolumeDirectoryFile;
|
||||
|
||||
struct CeosSARImageDesc ImageDesc;
|
||||
|
||||
Link_t * RecordList;
|
||||
} CeosSARVolume_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int ImageDescValue;
|
||||
int Override;
|
||||
int FileId;
|
||||
struct { unsigned char Subtype1,
|
||||
Type,
|
||||
Subtype2,
|
||||
Subtype3;
|
||||
} TypeCode;
|
||||
int Offset;
|
||||
int Length;
|
||||
int Type;
|
||||
} CeosRecipeType_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CeosRecipeType_t *Recipe;
|
||||
} CeosSARImageDescRecipe_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32 ValidFields;
|
||||
TBool SensorUpdate;
|
||||
int32 AcquisitionYear;
|
||||
int32 AcquisitionDay;
|
||||
int32 AcquisitionMsec;
|
||||
int32 TransmittedPolarization;
|
||||
int32 ReceivedPolarization;
|
||||
int32 PulsRepetitionFrequency;
|
||||
int32 SlantRangeFirstPixel;
|
||||
int32 SlantRangeMidPixel;
|
||||
int32 SlantRangeLastPixel;
|
||||
} CeosSAREmbeddedInfo_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double Slant[ 6 ];
|
||||
double Lut[ 512 ];
|
||||
double SemiMajorAxis;
|
||||
double PlatformLatitude;
|
||||
double CalibrationScale;
|
||||
int NumberOfSamples;
|
||||
int Increment;
|
||||
TBool PossiblyFlipped;
|
||||
|
||||
} CeosRadarCalibration_t;
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
void InitEmptyCeosRecord(CeosRecord_t *record, int32 sequence, CeosTypeCode_t typecode, int32 length);
|
||||
|
||||
void InitCeosRecord(CeosRecord_t *record, uchar *buffer);
|
||||
|
||||
void InitCeosRecordWithHeader(CeosRecord_t *record, uchar *header, uchar *buffer);
|
||||
|
||||
int DetermineCeosRecordBodyLength(const uchar *header);
|
||||
|
||||
void DeleteCeosRecord(CeosRecord_t *record);
|
||||
|
||||
void GetCeosRecordStruct(const CeosRecord_t *record, void *struct_ptr);
|
||||
|
||||
void PutCeosRecordStruct(CeosRecord_t *record, const void *struct_ptr);
|
||||
|
||||
void GetCeosField(CeosRecord_t *, int32, const char *, void *);
|
||||
|
||||
void SetCeosField(CeosRecord_t *record, int32 start_byte, char *format, void *value);
|
||||
|
||||
void SetIntCeosField(CeosRecord_t *record, int32 start_byte, int32 length, int32 value);
|
||||
|
||||
CeosRecord_t *FindCeosRecord(Link_t *record_list, CeosTypeCode_t typecode, int32 fileid, int32 flavour, int32 subsequence);
|
||||
|
||||
void SerializeCeosRecordsToFile(Link_t *record_list, VSILFILE *fp);
|
||||
|
||||
void SerializeCeosRecordsFromFile( Link_t *record_list, VSILFILE *fp );
|
||||
|
||||
void InitCeosSARVolume( CeosSARVolume_t *volume, int32 file_name_convention );
|
||||
|
||||
void GetCeosSARImageDesc( CeosSARVolume_t *volume );
|
||||
|
||||
void GetCeosSARImageDescInfo(CeosSARVolume_t *volume, CeosSARImageDescRecipe_t *recipe);
|
||||
|
||||
void CalcCeosSARImageFilePosition(CeosSARVolume_t *volume, int channel, int line, int *record, int *file_offset);
|
||||
|
||||
int32 GetCeosSARImageData(CeosSARVolume_t *volume, CeosRecord_t *processed_data_record, int channel, int xoff, int xsize, int bufsize, uchar *buffer);
|
||||
|
||||
void DetermineCeosSARPixelOrder(CeosSARVolume_t *volume, CeosRecord_t *record );
|
||||
|
||||
void GetCeosSAREmbeddedInfo(CeosSARVolume_t *volume, CeosRecord_t *processed_data_record, CeosSAREmbeddedInfo_t *info);
|
||||
|
||||
void DeleteCeosSARVolume(CeosSARVolume_t *volume);
|
||||
|
||||
void RegisterRecipes(void);
|
||||
void FreeRecipes();
|
||||
|
||||
void AddRecipe( int ( *function )( CeosSARVolume_t *volume, void *token ),
|
||||
void *token, const char *name );
|
||||
|
||||
int CeosDefaultRecipe( CeosSARVolume_t *volume, void *token );
|
||||
int ScanSARRecipeFCN( CeosSARVolume_t *volume, void *token );
|
||||
|
||||
/* ceoscalib.c function declarations */
|
||||
|
||||
CeosRadarCalibration_t *GetCeosRadarCalibration( CeosSARVolume_t *volume );
|
||||
|
||||
/* CEOS byte swapping stuff */
|
||||
|
||||
#if defined(CPL_MSB)
|
||||
#define NativeToCeos(a,b,c,d) memcpy(a,b,c)
|
||||
#define CeosToNative(a,b,c,d) memcpy(a,b,c)
|
||||
#else
|
||||
void NativeToCeos( void *dst, const void *src, const size_t len, const size_t swap_unit);
|
||||
#define CeosToNative(a,b,c,d) NativeToCeos(a,b,c,d)
|
||||
#endif
|
||||
|
||||
/* Recipe defines */
|
||||
|
||||
CPL_C_END
|
||||
|
||||
#endif
|
||||
758
bazaar/plugin/gdal/frmts/ceos2/ceosrecipe.c
Normal file
758
bazaar/plugin/gdal/frmts/ceos2/ceosrecipe.c
Normal file
|
|
@ -0,0 +1,758 @@
|
|||
/******************************************************************************
|
||||
* $Id: ceosrecipe.c 27745 2014-09-27 16:38:57Z goatbar $
|
||||
*
|
||||
* Project: ASI CEOS Translator
|
||||
* Purpose: CEOS field layout recipes.
|
||||
* Author: Paul Lahaie, pjlahaie@atlsci.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2000, Atlantis Scientific Inc
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "ceos.h"
|
||||
|
||||
CPL_CVSID("$Id: ceosrecipe.c 27745 2014-09-27 16:38:57Z goatbar $");
|
||||
|
||||
/* Array of Datatypes and their names/values */
|
||||
|
||||
typedef struct {
|
||||
char *String;
|
||||
int Type;
|
||||
} CeosStringType_t;
|
||||
|
||||
typedef struct {
|
||||
int (*function)(CeosSARVolume_t *volume, void *token);
|
||||
void *token;
|
||||
const char *name;
|
||||
} RecipeFunctionData_t;
|
||||
|
||||
|
||||
CeosStringType_t CeosDataType[] = { { "IU1", __CEOS_TYP_UCHAR },
|
||||
{ "IU2", __CEOS_TYP_USHORT },
|
||||
{ "UI1", __CEOS_TYP_UCHAR },
|
||||
{ "UI2", __CEOS_TYP_USHORT },
|
||||
{ "CI*2", __CEOS_TYP_COMPLEX_CHAR },
|
||||
{ "CI*4", __CEOS_TYP_COMPLEX_SHORT },
|
||||
{ "CIS4", __CEOS_TYP_COMPLEX_SHORT },
|
||||
{ "CI*8", __CEOS_TYP_COMPLEX_LONG },
|
||||
{ "C*8", __CEOS_TYP_COMPLEX_FLOAT },
|
||||
{ "R*4", __CEOS_TYP_FLOAT },
|
||||
{ NULL, 0 } };
|
||||
|
||||
CeosStringType_t CeosInterleaveType[] = { { "BSQ", __CEOS_IL_BAND },
|
||||
{ " BSQ", __CEOS_IL_BAND },
|
||||
{ "BIL", __CEOS_IL_LINE },
|
||||
{ " BIL", __CEOS_IL_LINE },
|
||||
{ NULL, 0 } };
|
||||
|
||||
#define IMAGE_OPT { 63, 192, 18, 18 }
|
||||
#define IMAGE_JERS_OPT { 50, 192, 18, 18 } /* Some JERS data uses this instead of IMAGE_OPT */
|
||||
#define PROC_DATA_REC { 50, 11, 18, 20 }
|
||||
#define PROC_DATA_REC_ALT { 50, 11, 31, 20 }
|
||||
#define PROC_DATA_REC_ALT2 { 50, 11, 31, 50 } /* Some cases of ERS 1, 2 */
|
||||
#define DATA_SET_SUMMARY { 18, 10, 18, 20 }
|
||||
|
||||
/* NOTE: This seems to be the generic recipe used for most things */
|
||||
CeosRecipeType_t RadarSatRecipe[] =
|
||||
{
|
||||
{ __CEOS_REC_NUMCHANS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
233, 4, __CEOS_REC_TYP_I }, /* Number of channels */
|
||||
{ __CEOS_REC_INTERLEAVE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
269, 4, __CEOS_REC_TYP_A }, /* Interleaving type */
|
||||
{ __CEOS_REC_DATATYPE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
429, 4, __CEOS_REC_TYP_A }, /* Data type */
|
||||
{ __CEOS_REC_BPR, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
0, 0, __CEOS_REC_TYP_A }, /* For Defeault CEOS, this is done using other vals */
|
||||
{ __CEOS_REC_LINES, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
237, 8, __CEOS_REC_TYP_I }, /* How many lines */
|
||||
{ __CEOS_REC_TBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
261, 4, __CEOS_REC_TYP_I },
|
||||
{ __CEOS_REC_BBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
265, 4, __CEOS_REC_TYP_I }, /* Bottom border pixels */
|
||||
{ __CEOS_REC_PPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
249, 8, __CEOS_REC_TYP_I }, /* Pixels per line */
|
||||
{ __CEOS_REC_LBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
245, 4, __CEOS_REC_TYP_I }, /* Left Border Pixels */
|
||||
{ __CEOS_REC_RBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
257, 4, __CEOS_REC_TYP_I }, /* Isn't available for RadarSAT */
|
||||
{ __CEOS_REC_BPP, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
225, 4, __CEOS_REC_TYP_I }, /* Bytes Per Pixel */
|
||||
{ __CEOS_REC_RPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
273, 2, __CEOS_REC_TYP_I }, /* Records per line */
|
||||
{ __CEOS_REC_PPR, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
0, 0, __CEOS_REC_TYP_I }, /* Pixels Per Record -- need to fill record type */
|
||||
{ __CEOS_REC_PDBPR, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
281, 8, __CEOS_REC_TYP_I }, /* pixel data bytes per record */
|
||||
{ __CEOS_REC_IDS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
277, 4, __CEOS_REC_TYP_I }, /* Prefix data per record */
|
||||
{ __CEOS_REC_FDL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
9, 4, __CEOS_REC_TYP_B }, /* Length of Imagry Options Header */
|
||||
{ __CEOS_REC_PIXORD, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
0, 0, __CEOS_REC_TYP_I }, /* Must be calculated */
|
||||
{ __CEOS_REC_LINORD, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
0, 0, __CEOS_REC_TYP_I }, /* Must be calculated */
|
||||
{ __CEOS_REC_PRODTYPE, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
0, 0, __CEOS_REC_TYP_I },
|
||||
|
||||
{ __CEOS_REC_RECORDSIZE, 1, __CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC,
|
||||
9, 4, __CEOS_REC_TYP_B }, /* The processed image record size */
|
||||
|
||||
/* Some ERS-1 products use an alternate data record subtype2. */
|
||||
{ __CEOS_REC_RECORDSIZE, 1, __CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC_ALT,
|
||||
9, 4, __CEOS_REC_TYP_B }, /* The processed image record size */
|
||||
|
||||
/* Yet another ERS-1 and ERS-2 alternate data record subtype2. */
|
||||
{ __CEOS_REC_RECORDSIZE, 1, __CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC_ALT2,
|
||||
9, 4, __CEOS_REC_TYP_B }, /* The processed image record size */
|
||||
|
||||
{ __CEOS_REC_SUFFIX_SIZE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
289, 4, __CEOS_REC_TYP_I }, /* Suffix data per record */
|
||||
{ 0, 0, 0, { 0, 0, 0, 0 }, 0, 0, 0 } /* Last record is Zero */
|
||||
} ;
|
||||
|
||||
|
||||
CeosRecipeType_t JersRecipe[] =
|
||||
{
|
||||
{ __CEOS_REC_NUMCHANS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
233, 4, __CEOS_REC_TYP_I }, /* Number of channels */
|
||||
{ __CEOS_REC_INTERLEAVE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
269, 4, __CEOS_REC_TYP_A }, /* Interleaving type */
|
||||
{ __CEOS_REC_DATATYPE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
429, 4, __CEOS_REC_TYP_A }, /* Data type */
|
||||
{ __CEOS_REC_BPR, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
0, 0, __CEOS_REC_TYP_A }, /* For Defeault CEOS, this is done using other vals */
|
||||
{ __CEOS_REC_LINES, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
237, 8, __CEOS_REC_TYP_I }, /* How many lines */
|
||||
{ __CEOS_REC_TBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
261, 4, __CEOS_REC_TYP_I },
|
||||
{ __CEOS_REC_BBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
265, 4, __CEOS_REC_TYP_I }, /* Bottom border pixels */
|
||||
{ __CEOS_REC_PPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
249, 8, __CEOS_REC_TYP_I }, /* Pixels per line */
|
||||
{ __CEOS_REC_LBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
245, 4, __CEOS_REC_TYP_I }, /* Left Border Pixels */
|
||||
{ __CEOS_REC_RBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
257, 4, __CEOS_REC_TYP_I }, /* Isn't available for RadarSAT */
|
||||
{ __CEOS_REC_BPP, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
225, 4, __CEOS_REC_TYP_I }, /* Bytes Per Pixel */
|
||||
{ __CEOS_REC_RPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
273, 2, __CEOS_REC_TYP_I }, /* Records per line */
|
||||
{ __CEOS_REC_PPR, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
0, 0, __CEOS_REC_TYP_I }, /* Pixels Per Record -- need to fill record type */
|
||||
{ __CEOS_REC_PDBPR, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
281, 8, __CEOS_REC_TYP_I }, /* pixel data bytes per record */
|
||||
{ __CEOS_REC_IDS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
277, 4, __CEOS_REC_TYP_I }, /* Prefix data per record */
|
||||
{ __CEOS_REC_FDL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
9, 4, __CEOS_REC_TYP_B }, /* Length of Imagry Options Header */
|
||||
{ __CEOS_REC_PIXORD, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
0, 0, __CEOS_REC_TYP_I }, /* Must be calculated */
|
||||
{ __CEOS_REC_LINORD, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
0, 0, __CEOS_REC_TYP_I }, /* Must be calculated */
|
||||
{ __CEOS_REC_PRODTYPE, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
0, 0, __CEOS_REC_TYP_I },
|
||||
|
||||
{ __CEOS_REC_RECORDSIZE, 1, __CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC,
|
||||
9, 4, __CEOS_REC_TYP_B }, /* The processed image record size */
|
||||
|
||||
{ __CEOS_REC_SUFFIX_SIZE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_JERS_OPT,
|
||||
289, 4, __CEOS_REC_TYP_I }, /* Suffix data per record */
|
||||
{ 0, 0, 0, { 0, 0, 0, 0 }, 0, 0, 0 } /* Last record is Zero */
|
||||
} ;
|
||||
|
||||
CeosRecipeType_t ScanSARRecipe[] =
|
||||
{
|
||||
{ __CEOS_REC_NUMCHANS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
233, 4, __CEOS_REC_TYP_I }, /* Number of channels */
|
||||
{ __CEOS_REC_INTERLEAVE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
269, 4, __CEOS_REC_TYP_A }, /* Interleaving type */
|
||||
{ __CEOS_REC_DATATYPE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
429, 4, __CEOS_REC_TYP_A }, /* Data type */
|
||||
{ __CEOS_REC_LINES, 1, __CEOS_ANY_FILE, DATA_SET_SUMMARY,
|
||||
325, 8, __CEOS_REC_TYP_I }, /* How many lines */
|
||||
{ __CEOS_REC_PPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
249, 8, __CEOS_REC_TYP_I }, /* Pixels per line */
|
||||
{ __CEOS_REC_BPP, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
225, 4, __CEOS_REC_TYP_I }, /* Bytes Per Pixel */
|
||||
{ __CEOS_REC_RPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
273, 2, __CEOS_REC_TYP_I }, /* Records per line */
|
||||
{ __CEOS_REC_IDS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
277, 4, __CEOS_REC_TYP_I }, /* Prefix data per record */
|
||||
{ __CEOS_REC_FDL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
9, 4, __CEOS_REC_TYP_B }, /* Length of Imagry Options Header */
|
||||
{ __CEOS_REC_RECORDSIZE, 1, __CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC,
|
||||
9, 4, __CEOS_REC_TYP_B }, /* The processed image record size */
|
||||
{ __CEOS_REC_SUFFIX_SIZE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
289, 4, __CEOS_REC_TYP_I }, /* Suffix data per record */
|
||||
{ 0, 0, 0, { 0, 0, 0, 0 }, 0, 0, 0 } /* Last record is Zero */
|
||||
} ;
|
||||
|
||||
CeosRecipeType_t SIRCRecipe[] =
|
||||
{
|
||||
{ __CEOS_REC_NUMCHANS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
233, 4, __CEOS_REC_TYP_I }, /* Number of channels */
|
||||
{ __CEOS_REC_INTERLEAVE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
269, 4, __CEOS_REC_TYP_A }, /* Interleaving type */
|
||||
{ __CEOS_REC_DATATYPE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
429, 4, __CEOS_REC_TYP_A }, /* Data type */
|
||||
{ __CEOS_REC_LINES, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
237, 8, __CEOS_REC_TYP_I }, /* How many lines */
|
||||
{ __CEOS_REC_TBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
261, 4, __CEOS_REC_TYP_I },
|
||||
{ __CEOS_REC_BBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
265, 4, __CEOS_REC_TYP_I }, /* Bottom border pixels */
|
||||
{ __CEOS_REC_PPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
249, 8, __CEOS_REC_TYP_I }, /* Pixels per line */
|
||||
{ __CEOS_REC_LBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
245, 4, __CEOS_REC_TYP_I }, /* Left Border Pixels */
|
||||
{ __CEOS_REC_RBP, 0, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
257, 4, __CEOS_REC_TYP_I }, /* Right Border Pixels */
|
||||
{ __CEOS_REC_BPP, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
225, 4, __CEOS_REC_TYP_I }, /* Bytes Per Pixel */
|
||||
{ __CEOS_REC_RPL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
273, 2, __CEOS_REC_TYP_I }, /* Records per line */
|
||||
{ __CEOS_REC_IDS, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
277, 4, __CEOS_REC_TYP_I }, /* Prefix data per record */
|
||||
{ __CEOS_REC_FDL, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
9, 4, __CEOS_REC_TYP_B }, /* Length of Imagry Options Header */
|
||||
{ __CEOS_REC_RECORDSIZE, 1, __CEOS_IMAGRY_OPT_FILE, PROC_DATA_REC,
|
||||
9, 4, __CEOS_REC_TYP_B }, /* The processed image record size */
|
||||
{ __CEOS_REC_SUFFIX_SIZE, 1, __CEOS_IMAGRY_OPT_FILE, IMAGE_OPT,
|
||||
289, 4, __CEOS_REC_TYP_I }, /* Suffix data per record */
|
||||
|
||||
{ 0, 0, 0, { 0, 0, 0, 0 }, 0, 0, 0 } /* Last record is Zero */
|
||||
} ;
|
||||
|
||||
#undef PROC_DATA_REC
|
||||
|
||||
static void ExtractInt( CeosRecord_t *record, int type, unsigned int offset, unsigned int length, int *value );
|
||||
|
||||
static char *ExtractString( CeosRecord_t *record, unsigned int offset, unsigned int length, char *string );
|
||||
|
||||
static int GetCeosStringType(const CeosStringType_t *CeosType, const char *string);
|
||||
|
||||
static int SIRCRecipeFCN( CeosSARVolume_t *volume, void *token );
|
||||
static int PALSARRecipeFCN( CeosSARVolume_t *volume, void *token );
|
||||
|
||||
Link_t *RecipeFunctions = NULL;
|
||||
|
||||
void RegisterRecipes( void )
|
||||
{
|
||||
|
||||
AddRecipe( SIRCRecipeFCN, SIRCRecipe, "SIR-C" );
|
||||
AddRecipe( ScanSARRecipeFCN, ScanSARRecipe, "ScanSAR" );
|
||||
AddRecipe( CeosDefaultRecipe, RadarSatRecipe, "RadarSat" );
|
||||
AddRecipe( CeosDefaultRecipe, JersRecipe, "Jers" );
|
||||
AddRecipe( PALSARRecipeFCN, RadarSatRecipe, "PALSAR-ALOS" );
|
||||
/* AddRecipe( CeosDefaultRecipe, AtlantisRecipe ); */
|
||||
}
|
||||
|
||||
void FreeRecipes( void )
|
||||
|
||||
{
|
||||
Link_t *link;
|
||||
|
||||
for( link = RecipeFunctions; link != NULL; link = link->next )
|
||||
HFree( link->object );
|
||||
|
||||
DestroyList( RecipeFunctions );
|
||||
RecipeFunctions = NULL;
|
||||
}
|
||||
|
||||
void AddRecipe( int (*function)(CeosSARVolume_t *volume,
|
||||
void *token),
|
||||
void *token,
|
||||
const char *name )
|
||||
{
|
||||
|
||||
RecipeFunctionData_t *TempData;
|
||||
|
||||
Link_t *Link;
|
||||
|
||||
TempData = HMalloc( sizeof( RecipeFunctionData_t ) );
|
||||
|
||||
TempData->function = function;
|
||||
TempData->token = token;
|
||||
TempData->name = name;
|
||||
|
||||
Link = ceos2CreateLink( TempData );
|
||||
|
||||
if( RecipeFunctions == NULL)
|
||||
{
|
||||
RecipeFunctions = Link;
|
||||
} else {
|
||||
RecipeFunctions = InsertLink( RecipeFunctions, Link );
|
||||
}
|
||||
}
|
||||
|
||||
int CeosDefaultRecipe( CeosSARVolume_t *volume, void *token )
|
||||
{
|
||||
CeosRecipeType_t *recipe;
|
||||
CeosRecord_t *record;
|
||||
CeosTypeCode_t TypeCode;
|
||||
struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
|
||||
char temp_str[1024];
|
||||
int i /*, temp_int */;
|
||||
|
||||
#define DoExtractInt(a) ExtractInt( record, recipe[i].Type, recipe[i].Offset, recipe[i].Length, &a)
|
||||
|
||||
if(token == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(ImageDesc, 0, sizeof( struct CeosSARImageDesc ) );
|
||||
|
||||
/* temp_imagerecipe = (CeosSARImageDescRecipe_t *) token;
|
||||
recipe = temp_imagerecipe->Recipe; */
|
||||
|
||||
recipe = token;
|
||||
|
||||
for(i = 0; recipe[i].ImageDescValue != 0; i++ )
|
||||
{
|
||||
if(recipe[i].Override)
|
||||
{
|
||||
TypeCode.UCharCode.Subtype1 = recipe[i].TypeCode.Subtype1;
|
||||
TypeCode.UCharCode.Type = recipe[i].TypeCode.Type;
|
||||
TypeCode.UCharCode.Subtype2 = recipe[i].TypeCode.Subtype2;
|
||||
TypeCode.UCharCode.Subtype3 = recipe[i].TypeCode.Subtype3;
|
||||
|
||||
record = FindCeosRecord( volume->RecordList, TypeCode, recipe[i].FileId, -1, -1 );
|
||||
|
||||
if(record == NULL)
|
||||
{
|
||||
/* temp_int = 0; */
|
||||
} else {
|
||||
|
||||
switch( recipe[i].ImageDescValue )
|
||||
{
|
||||
case __CEOS_REC_NUMCHANS:
|
||||
DoExtractInt( ImageDesc->NumChannels );
|
||||
break;
|
||||
case __CEOS_REC_LINES:
|
||||
DoExtractInt( ImageDesc->Lines );
|
||||
break;
|
||||
case __CEOS_REC_BPP:
|
||||
DoExtractInt( ImageDesc->BytesPerPixel );
|
||||
break;
|
||||
case __CEOS_REC_RPL:
|
||||
DoExtractInt( ImageDesc->RecordsPerLine );
|
||||
break;
|
||||
case __CEOS_REC_PDBPR:
|
||||
DoExtractInt( ImageDesc->PixelDataBytesPerRecord );
|
||||
break;
|
||||
case __CEOS_REC_FDL:
|
||||
DoExtractInt( ImageDesc->FileDescriptorLength );
|
||||
break;
|
||||
case __CEOS_REC_IDS:
|
||||
DoExtractInt( ImageDesc->ImageDataStart );
|
||||
/*
|
||||
** This is really reading the quantity of prefix data
|
||||
** per data record. We want the offset from the very
|
||||
** beginning of the record to the data, so we add another
|
||||
** 12 to that. I think some products incorrectly indicate
|
||||
** 192 (prefix+12) instead of 180 so if we see 192 assume
|
||||
** the 12 bytes of record start data has already been
|
||||
** added. Frank Warmerdam.
|
||||
*/
|
||||
if( ImageDesc->ImageDataStart != 192 )
|
||||
ImageDesc->ImageDataStart += 12;
|
||||
break;
|
||||
case __CEOS_REC_SUFFIX_SIZE:
|
||||
DoExtractInt( ImageDesc->ImageSuffixData );
|
||||
break;
|
||||
case __CEOS_REC_RECORDSIZE:
|
||||
DoExtractInt( ImageDesc->BytesPerRecord );
|
||||
break;
|
||||
case __CEOS_REC_PPL:
|
||||
DoExtractInt( ImageDesc->PixelsPerLine );
|
||||
break;
|
||||
case __CEOS_REC_TBP:
|
||||
DoExtractInt( ImageDesc->TopBorderPixels );
|
||||
break;
|
||||
case __CEOS_REC_BBP:
|
||||
DoExtractInt( ImageDesc->BottomBorderPixels );
|
||||
break;
|
||||
case __CEOS_REC_LBP:
|
||||
DoExtractInt( ImageDesc->LeftBorderPixels );
|
||||
break;
|
||||
case __CEOS_REC_RBP:
|
||||
DoExtractInt( ImageDesc->RightBorderPixels );
|
||||
break;
|
||||
case __CEOS_REC_INTERLEAVE:
|
||||
ExtractString( record, recipe[i].Offset, recipe[i].Length, temp_str );
|
||||
|
||||
ImageDesc->ChannelInterleaving = GetCeosStringType( CeosInterleaveType, temp_str );
|
||||
break;
|
||||
case __CEOS_REC_DATATYPE:
|
||||
ExtractString( record, recipe[i].Offset, recipe[i].Length, temp_str );
|
||||
|
||||
ImageDesc->DataType = GetCeosStringType( CeosDataType, temp_str );
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Some files (Telaviv) don't record the number of pixel groups per line.
|
||||
* Try to derive it from the size of a data group, and the number of
|
||||
* bytes of pixel data if necessary.
|
||||
*/
|
||||
|
||||
if( ImageDesc->PixelsPerLine == 0
|
||||
&& ImageDesc->PixelDataBytesPerRecord != 0
|
||||
&& ImageDesc->BytesPerPixel != 0 )
|
||||
{
|
||||
ImageDesc->PixelsPerLine =
|
||||
ImageDesc->PixelDataBytesPerRecord / ImageDesc->BytesPerPixel;
|
||||
CPLDebug( "SAR_CEOS", "Guessing PixelPerLine to be %d\n",
|
||||
ImageDesc->PixelsPerLine );
|
||||
}
|
||||
|
||||
/* Some files don't have the BytesPerRecord stuff, so we calculate it if possible */
|
||||
|
||||
if( ImageDesc->BytesPerRecord == 0 && ImageDesc->RecordsPerLine == 1 &&
|
||||
ImageDesc->PixelsPerLine > 0 && ImageDesc->BytesPerPixel > 0 )
|
||||
{
|
||||
CeosRecord_t *img_rec;
|
||||
|
||||
ImageDesc->BytesPerRecord = ImageDesc->PixelsPerLine *
|
||||
ImageDesc->BytesPerPixel + ImageDesc->ImageDataStart +
|
||||
ImageDesc->ImageSuffixData ;
|
||||
|
||||
TypeCode.UCharCode.Subtype1 = 0xed;
|
||||
TypeCode.UCharCode.Type = 0xed;
|
||||
TypeCode.UCharCode.Subtype2 = 0x12;
|
||||
TypeCode.UCharCode.Subtype3 = 0x12;
|
||||
|
||||
img_rec = FindCeosRecord( volume->RecordList, TypeCode,
|
||||
__CEOS_IMAGRY_OPT_FILE, -1, -1 );
|
||||
if( img_rec == NULL )
|
||||
{
|
||||
CPLDebug( "SAR_CEOS",
|
||||
"Unable to find imagery rec to check record length." );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( img_rec->Length != ImageDesc->BytesPerRecord )
|
||||
{
|
||||
CPLDebug( "SAR_CEOS",
|
||||
"Guessed record length (%d) did not match\n"
|
||||
"actual imagery record length (%d), recipe fails.",
|
||||
ImageDesc->BytesPerRecord, img_rec->Length );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( ImageDesc->PixelsPerRecord == 0 &&
|
||||
ImageDesc->BytesPerRecord != 0 && ImageDesc->BytesPerPixel != 0 )
|
||||
{
|
||||
ImageDesc->PixelsPerRecord = ( ( ImageDesc->BytesPerRecord -
|
||||
(ImageDesc->ImageSuffixData +
|
||||
ImageDesc->ImageDataStart )) /
|
||||
ImageDesc->BytesPerPixel );
|
||||
|
||||
if(ImageDesc->PixelsPerRecord > ImageDesc->PixelsPerLine)
|
||||
ImageDesc->PixelsPerRecord = ImageDesc->PixelsPerLine;
|
||||
}
|
||||
|
||||
/* If we didn't get a data type, try guessing. */
|
||||
if( ImageDesc->DataType == 0
|
||||
&& ImageDesc->BytesPerPixel != 0
|
||||
&& ImageDesc->NumChannels != 0 )
|
||||
{
|
||||
int nDataTypeSize = ImageDesc->BytesPerPixel / ImageDesc->NumChannels;
|
||||
|
||||
if( nDataTypeSize == 1 )
|
||||
ImageDesc->DataType = __CEOS_TYP_UCHAR;
|
||||
else if( nDataTypeSize == 2 )
|
||||
ImageDesc->DataType = __CEOS_TYP_USHORT;
|
||||
}
|
||||
|
||||
/* Sanity checking */
|
||||
|
||||
if( ImageDesc->PixelsPerLine == 0 || ImageDesc->Lines == 0 ||
|
||||
ImageDesc->RecordsPerLine == 0 || ImageDesc->ImageDataStart == 0 ||
|
||||
ImageDesc->FileDescriptorLength == 0 || ImageDesc->DataType == 0 ||
|
||||
ImageDesc->NumChannels == 0 || ImageDesc->BytesPerPixel == 0 ||
|
||||
ImageDesc->ChannelInterleaving == 0 || ImageDesc->BytesPerRecord == 0)
|
||||
{
|
||||
return 0;
|
||||
} else {
|
||||
|
||||
ImageDesc->ImageDescValid = TRUE;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int ScanSARRecipeFCN( CeosSARVolume_t *volume, void *token )
|
||||
{
|
||||
struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
|
||||
|
||||
memset( ImageDesc, 0, sizeof( struct CeosSARImageDesc ) );
|
||||
|
||||
if( CeosDefaultRecipe( volume, token ) )
|
||||
{
|
||||
ImageDesc->Lines *= 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SIRCRecipeFCN( CeosSARVolume_t *volume, void *token )
|
||||
{
|
||||
struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
|
||||
CeosTypeCode_t TypeCode;
|
||||
CeosRecord_t *record;
|
||||
char szSARDataFormat[29];
|
||||
|
||||
memset( ImageDesc, 0, sizeof( struct CeosSARImageDesc ) );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* First, we need to check if the "SAR Data Format Type */
|
||||
/* identifier" is set to "COMPRESSED CROSS-PRODUCTS" which is */
|
||||
/* pretty idiosyncratic to SIRC products. It might also appear */
|
||||
/* for some other similarly encoded Polarimetric data I suppose. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* IMAGE_OPT */
|
||||
TypeCode.UCharCode.Subtype1 = 63;
|
||||
TypeCode.UCharCode.Type = 192;
|
||||
TypeCode.UCharCode.Subtype2 = 18;
|
||||
TypeCode.UCharCode.Subtype3 = 18;
|
||||
|
||||
record = FindCeosRecord( volume->RecordList, TypeCode,
|
||||
__CEOS_IMAGRY_OPT_FILE, -1, -1 );
|
||||
if( record == NULL )
|
||||
return 0;
|
||||
|
||||
ExtractString( record, 401, 28, szSARDataFormat );
|
||||
if( !EQUALN( szSARDataFormat, "COMPRESSED CROSS-PRODUCTS", 25) )
|
||||
return 0;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Apply normal handling... */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CeosDefaultRecipe( volume, token );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Make sure this looks like the SIRC product we are expecting. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( ImageDesc->BytesPerPixel != 10 )
|
||||
return 0;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Then fix up a few values. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* It seems the bytes of pixel data per record is just wrong. Fix. */
|
||||
ImageDesc->PixelDataBytesPerRecord =
|
||||
ImageDesc->BytesPerPixel * ImageDesc->PixelsPerLine;
|
||||
|
||||
ImageDesc->DataType = __CEOS_TYP_CCP_COMPLEX_FLOAT;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Sanity checking */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( ImageDesc->PixelsPerLine == 0 || ImageDesc->Lines == 0 ||
|
||||
ImageDesc->RecordsPerLine == 0 || ImageDesc->ImageDataStart == 0 ||
|
||||
ImageDesc->FileDescriptorLength == 0 || ImageDesc->DataType == 0 ||
|
||||
ImageDesc->NumChannels == 0 || ImageDesc->BytesPerPixel == 0 ||
|
||||
ImageDesc->ChannelInterleaving == 0 || ImageDesc->BytesPerRecord == 0)
|
||||
{
|
||||
return 0;
|
||||
} else {
|
||||
|
||||
ImageDesc->ImageDescValid = TRUE;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int PALSARRecipeFCN( CeosSARVolume_t *volume, void *token )
|
||||
{
|
||||
struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
|
||||
CeosTypeCode_t TypeCode;
|
||||
CeosRecord_t *record;
|
||||
char szSARDataFormat[29], szProduct[32];
|
||||
|
||||
memset( ImageDesc, 0, sizeof( struct CeosSARImageDesc ) );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* First, we need to check if the "SAR Data Format Type */
|
||||
/* identifier" is set to "COMPRESSED CROSS-PRODUCTS" which is */
|
||||
/* pretty idiosyncratic to SIRC products. It might also appear */
|
||||
/* for some other similarly encoded Polarimetric data I suppose. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* IMAGE_OPT */
|
||||
TypeCode.UCharCode.Subtype1 = 63;
|
||||
TypeCode.UCharCode.Type = 192;
|
||||
TypeCode.UCharCode.Subtype2 = 18;
|
||||
TypeCode.UCharCode.Subtype3 = 18;
|
||||
|
||||
record = FindCeosRecord( volume->RecordList, TypeCode,
|
||||
__CEOS_IMAGRY_OPT_FILE, -1, -1 );
|
||||
if( record == NULL )
|
||||
return 0;
|
||||
|
||||
ExtractString( record, 401, 28, szSARDataFormat );
|
||||
if( !EQUALN( szSARDataFormat, "INTEGER*18 ", 25) )
|
||||
return 0;
|
||||
|
||||
ExtractString( record, 49, 16, szProduct );
|
||||
if( !EQUALN( szProduct, "ALOS-", 5 ) )
|
||||
return 0;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Apply normal handling... */
|
||||
/* -------------------------------------------------------------------- */
|
||||
CeosDefaultRecipe( volume, token );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Make sure this looks like the SIRC product we are expecting. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( ImageDesc->BytesPerPixel != 18 )
|
||||
return 0;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Then fix up a few values. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
ImageDesc->DataType = __CEOS_TYP_PALSAR_COMPLEX_SHORT;
|
||||
ImageDesc->NumChannels = 6;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Sanity checking */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( ImageDesc->PixelsPerLine == 0 || ImageDesc->Lines == 0 ||
|
||||
ImageDesc->RecordsPerLine == 0 || ImageDesc->ImageDataStart == 0 ||
|
||||
ImageDesc->FileDescriptorLength == 0 || ImageDesc->DataType == 0 ||
|
||||
ImageDesc->NumChannels == 0 || ImageDesc->BytesPerPixel == 0 ||
|
||||
ImageDesc->ChannelInterleaving == 0 || ImageDesc->BytesPerRecord == 0)
|
||||
{
|
||||
return 0;
|
||||
} else {
|
||||
|
||||
ImageDesc->ImageDescValid = TRUE;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void GetCeosSARImageDesc( CeosSARVolume_t *volume )
|
||||
{
|
||||
Link_t *link;
|
||||
RecipeFunctionData_t *rec_data;
|
||||
int (*function)(CeosSARVolume_t *volume, void *token);
|
||||
|
||||
if( RecipeFunctions == NULL )
|
||||
{
|
||||
RegisterRecipes();
|
||||
}
|
||||
|
||||
if(RecipeFunctions == NULL )
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
for(link = RecipeFunctions; link != NULL; link = link->next)
|
||||
{
|
||||
if(link->object)
|
||||
{
|
||||
rec_data = link->object;
|
||||
function = rec_data->function;
|
||||
if(( *function )( volume, rec_data->token ) )
|
||||
{
|
||||
CPLDebug( "CEOS", "Using recipe '%s'.",
|
||||
rec_data->name );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void ExtractInt(CeosRecord_t *record, int type, unsigned int offset, unsigned int length, int *value)
|
||||
{
|
||||
void *buffer;
|
||||
char format[32];
|
||||
|
||||
buffer = HMalloc( length + 1 );
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case __CEOS_REC_TYP_A:
|
||||
sprintf( format, "A%u", length );
|
||||
GetCeosField( record, offset, format, buffer );
|
||||
*value = atoi( buffer );
|
||||
break;
|
||||
case __CEOS_REC_TYP_B:
|
||||
sprintf( format, "B%u", length );
|
||||
#ifdef notdef
|
||||
GetCeosField( record, offset, format, buffer );
|
||||
if( length <= 4 )
|
||||
CeosToNative( value, buffer, length, length );
|
||||
else
|
||||
*value = 0;
|
||||
#else
|
||||
GetCeosField( record, offset, format, value );
|
||||
#endif
|
||||
break;
|
||||
case __CEOS_REC_TYP_I:
|
||||
sprintf( format, "I%u", length );
|
||||
GetCeosField( record, offset, format, value );
|
||||
break;
|
||||
}
|
||||
|
||||
HFree( buffer );
|
||||
|
||||
}
|
||||
|
||||
static char *ExtractString( CeosRecord_t *record, unsigned int offset, unsigned int length, char *string )
|
||||
{
|
||||
char format[12];
|
||||
|
||||
if(string == NULL)
|
||||
{
|
||||
string = HMalloc( length + 1 );
|
||||
}
|
||||
|
||||
sprintf( format, "A%u", length );
|
||||
|
||||
GetCeosField( record, offset, format, string );
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
static int GetCeosStringType(const CeosStringType_t *CeosStringType, const char *string)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0;CeosStringType[i].String != NULL;i++)
|
||||
{
|
||||
if(strncmp(CeosStringType[i].String ,string, strlen( CeosStringType[i].String ) ) == 0 )
|
||||
{
|
||||
return CeosStringType[i].Type;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
139
bazaar/plugin/gdal/frmts/ceos2/ceossar.c
Normal file
139
bazaar/plugin/gdal/frmts/ceos2/ceossar.c
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/******************************************************************************
|
||||
* $Id: ceossar.c 27745 2014-09-27 16:38:57Z goatbar $
|
||||
*
|
||||
* Project: ASI CEOS Translator
|
||||
* Purpose: Functions related to CeosSARVolume_t.
|
||||
* Author: Paul Lahaie, pjlahaie@atlsci.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2000, Atlantis Scientific Inc
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "ceos.h"
|
||||
|
||||
CPL_CVSID("$Id: ceossar.c 27745 2014-09-27 16:38:57Z goatbar $");
|
||||
|
||||
extern Link_t *RecipeFunctions;
|
||||
|
||||
void InitCeosSARVolume(CeosSARVolume_t *volume, int32 file_name_convention)
|
||||
{
|
||||
volume->Flavour = \
|
||||
volume->Sensor = \
|
||||
volume->ProductType = 0;
|
||||
|
||||
volume->FileNamingConvention = file_name_convention ;
|
||||
|
||||
volume->VolumeDirectoryFile =
|
||||
volume->SARLeaderFile =
|
||||
volume->SARTrailerFile =
|
||||
volume->NullVolumeDirectoryFile =
|
||||
volume->ImageDesc.ImageDescValid = FALSE;
|
||||
|
||||
volume->RecordList = NULL;
|
||||
}
|
||||
|
||||
|
||||
void CalcCeosSARImageFilePosition(CeosSARVolume_t *volume, int channel, int line, int *record, int *file_offset)
|
||||
{
|
||||
struct CeosSARImageDesc *ImageDesc;
|
||||
int TotalRecords=0, TotalBytes=0;
|
||||
|
||||
if(record)
|
||||
*record = 0;
|
||||
if(file_offset)
|
||||
*file_offset = 0;
|
||||
|
||||
if( volume )
|
||||
{
|
||||
if( volume->ImageDesc.ImageDescValid )
|
||||
{
|
||||
ImageDesc = &( volume->ImageDesc );
|
||||
|
||||
switch( ImageDesc->ChannelInterleaving )
|
||||
{
|
||||
case __CEOS_IL_PIXEL:
|
||||
TotalRecords = (line - 1) * ImageDesc->RecordsPerLine;
|
||||
TotalBytes = (TotalRecords) * ( ImageDesc->BytesPerRecord );
|
||||
break;
|
||||
case __CEOS_IL_LINE:
|
||||
TotalRecords = (ImageDesc->NumChannels * (line - 1) +
|
||||
(channel - 1)) * ImageDesc->RecordsPerLine;
|
||||
TotalBytes = (TotalRecords) * ( ImageDesc->BytesPerRecord ) ;
|
||||
break;
|
||||
case __CEOS_IL_BAND:
|
||||
TotalRecords = (((channel - 1) * ImageDesc->Lines) *
|
||||
ImageDesc->RecordsPerLine) +
|
||||
(line - 1) * ImageDesc->RecordsPerLine;
|
||||
|
||||
TotalBytes = (TotalRecords) * ( ImageDesc->BytesPerRecord );
|
||||
break;
|
||||
}
|
||||
if(file_offset)
|
||||
*file_offset = ImageDesc->FileDescriptorLength + TotalBytes;
|
||||
if(record)
|
||||
*record = TotalRecords + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32 GetCeosSARImageData(CPL_UNUSED CeosSARVolume_t *volume,
|
||||
CPL_UNUSED CeosRecord_t *processed_data_record,
|
||||
CPL_UNUSED int channel,
|
||||
CPL_UNUSED int xoff,
|
||||
CPL_UNUSED int xsize,
|
||||
CPL_UNUSED int bufsize,
|
||||
CPL_UNUSED uchar *buffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DetermineCeosSARPixelOrder( CPL_UNUSED CeosSARVolume_t *volume,
|
||||
CPL_UNUSED CeosRecord_t *record )
|
||||
{
|
||||
}
|
||||
|
||||
void GetCeosSAREmbeddedInfo(CPL_UNUSED CeosSARVolume_t *volume,
|
||||
CPL_UNUSED CeosRecord_t *processed_data_record,
|
||||
CPL_UNUSED CeosSAREmbeddedInfo_t *info)
|
||||
{
|
||||
}
|
||||
|
||||
void DeleteCeosSARVolume(CeosSARVolume_t *volume)
|
||||
{
|
||||
Link_t *Links;
|
||||
|
||||
if( volume )
|
||||
{
|
||||
if( volume->RecordList )
|
||||
{
|
||||
for(Links = volume->RecordList; Links != NULL; Links = Links->next)
|
||||
{
|
||||
if(Links->object)
|
||||
{
|
||||
DeleteCeosRecord( Links->object );
|
||||
Links->object = NULL;
|
||||
}
|
||||
}
|
||||
DestroyList( volume->RecordList );
|
||||
}
|
||||
HFree( volume );
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue