Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code cleanup in VRTKernelFilteredSource #10257

Merged
merged 2 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions autotest/gdrivers/vrtfilt.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,3 +238,27 @@ def test_vrtfilt_invalid_kernel_size():

with pytest.raises(Exception):
vrt_ds.GetRasterBand(1).SetMetadata(md, "vrt_sources")


###############################################################################


def test_vrtfilt_serialize_separatable_kernel():

vrt_ds = gdal.GetDriverByName("VRT").Create("", 1, 1, 1)

filterSourceXML = """<KernelFilteredSource>
<SourceFilename relativeToVRT="0">data/rgbsmall.tif</SourceFilename>
<SourceBand>1</SourceBand>
<Kernel normalized="0">
<Size>3</Size>
<Coefs>1 1 1</Coefs>
</Kernel>
</KernelFilteredSource>"""

md = {}
md["source_0"] = filterSourceXML

vrt_ds.GetRasterBand(1).SetMetadata(md, "vrt_sources")

assert filterSourceXML in vrt_ds.GetMetadata("xml:VRT")[0]
18 changes: 8 additions & 10 deletions frmts/vrt/vrtdataset.h
Original file line number Diff line number Diff line change
Expand Up @@ -1601,17 +1601,14 @@ class VRTKernelFilteredSource CPL_NON_FINAL : public VRTFilteredSource
CPL_DISALLOW_COPY_ASSIGN(VRTKernelFilteredSource)

protected:
int m_nKernelSize;

bool m_bSeparable;

double *m_padfKernelCoefs;

int m_bNormalized;
int m_nKernelSize = 0;
bool m_bSeparable = false;
// m_nKernelSize elements if m_bSeparable, m_nKernelSize * m_nKernelSize otherwise
std::vector<double> m_adfKernelCoefs{};
bool m_bNormalized = false;

public:
VRTKernelFilteredSource();
virtual ~VRTKernelFilteredSource();

virtual CPLErr XMLInit(const CPLXMLNode *psTree, const char *,
std::map<CPLString, GDALDataset *> &) override;
Expand All @@ -1620,8 +1617,9 @@ class VRTKernelFilteredSource CPL_NON_FINAL : public VRTFilteredSource
virtual CPLErr FilterData(int nXSize, int nYSize, GDALDataType eType,
GByte *pabySrcData, GByte *pabyDstData) override;

CPLErr SetKernel(int nKernelSize, bool bSeparable, double *padfCoefs);
void SetNormalized(int);
CPLErr SetKernel(int nKernelSize, bool bSeparable,
const std::vector<double> &adfNewCoefs);
void SetNormalized(bool);
};

/************************************************************************/
Expand Down
97 changes: 37 additions & 60 deletions frmts/vrt/vrtfilters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,28 +420,16 @@ CPLErr VRTFilteredSource::RasterIO(GDALDataType eVRTBandDataType, int nXOff,
/************************************************************************/

VRTKernelFilteredSource::VRTKernelFilteredSource()
: m_nKernelSize(0), m_bSeparable(FALSE), m_padfKernelCoefs(nullptr),
m_bNormalized(FALSE)
{
GDALDataType aeSupTypes[] = {GDT_Float32};
SetFilteringDataTypesSupported(1, aeSupTypes);
}

/************************************************************************/
/* ~VRTKernelFilteredSource() */
/************************************************************************/

VRTKernelFilteredSource::~VRTKernelFilteredSource()

{
CPLFree(m_padfKernelCoefs);
}

/************************************************************************/
/* SetNormalized() */
/************************************************************************/

void VRTKernelFilteredSource::SetNormalized(int bNormalizedIn)
void VRTKernelFilteredSource::SetNormalized(bool bNormalizedIn)

{
m_bNormalized = bNormalizedIn;
Expand All @@ -451,8 +439,9 @@ void VRTKernelFilteredSource::SetNormalized(int bNormalizedIn)
/* SetKernel() */
/************************************************************************/

CPLErr VRTKernelFilteredSource::SetKernel(int nNewKernelSize, bool bSeparable,
double *padfNewCoefs)
CPLErr
VRTKernelFilteredSource::SetKernel(int nNewKernelSize, bool bSeparable,
const std::vector<double> &adfNewCoefs)

{
if (nNewKernelSize < 1 || (nNewKernelSize % 2) != 1)
Expand All @@ -463,16 +452,17 @@ CPLErr VRTKernelFilteredSource::SetKernel(int nNewKernelSize, bool bSeparable,
nNewKernelSize);
return CE_Failure;
}
if (adfNewCoefs.size() !=
static_cast<size_t>(nNewKernelSize) * (bSeparable ? 1 : nNewKernelSize))
{
CPLError(CE_Failure, CPLE_AppDefined,
"adfNewCoefs[] is not of expected size");
return CE_Failure;
}

CPLFree(m_padfKernelCoefs);
m_nKernelSize = nNewKernelSize;
m_bSeparable = bSeparable;

int nKernelBufferSize = m_nKernelSize * (m_bSeparable ? 1 : m_nKernelSize);

m_padfKernelCoefs =
static_cast<double *>(CPLMalloc(sizeof(double) * nKernelBufferSize));
memcpy(m_padfKernelCoefs, padfNewCoefs, sizeof(double) * nKernelBufferSize);
m_adfKernelCoefs = adfNewCoefs;

SetExtraEdgePixels((nNewKernelSize - 1) / 2);

Expand Down Expand Up @@ -565,8 +555,8 @@ CPLErr VRTKernelFilteredSource::FilterData(int nXSize, int nYSize,
iJJ * nJStride;
if (bHasNoData && *pfData == fNoData)
continue;
dfSum += *pfData * m_padfKernelCoefs[iK];
dfKernSum += m_padfKernelCoefs[iK];
dfSum += *pfData * m_adfKernelCoefs[iK];
dfKernSum += m_adfKernelCoefs[iK];
}
}

Expand Down Expand Up @@ -618,17 +608,16 @@ CPLErr VRTKernelFilteredSource::XMLInit(
return CE_Failure;
}

char **papszCoefItems =
CSLTokenizeString(CPLGetXMLValue(psTree, "Kernel.Coefs", ""));
const CPLStringList aosCoefItems(
CSLTokenizeString(CPLGetXMLValue(psTree, "Kernel.Coefs", "")));

const int nCoefs = CSLCount(papszCoefItems);
const int nCoefs = aosCoefItems.size();

const bool bSquare = nCoefs == nNewKernelSize * nNewKernelSize;
const bool bSeparable = nCoefs == nNewKernelSize && nCoefs != 1;

if (!bSquare && !bSeparable)
{
CSLDestroy(papszCoefItems);
CPLError(CE_Failure, CPLE_AppDefined,
"Got wrong number of filter kernel coefficients (%s). "
"Expected %d or %d, got %d.",
Expand All @@ -637,19 +626,17 @@ CPLErr VRTKernelFilteredSource::XMLInit(
return CE_Failure;
}

double *padfNewCoefs =
static_cast<double *>(CPLMalloc(sizeof(double) * nCoefs));

std::vector<double> adfNewCoefs;
adfNewCoefs.reserve(nCoefs);
for (int i = 0; i < nCoefs; i++)
padfNewCoefs[i] = CPLAtof(papszCoefItems[i]);

const CPLErr eErr = SetKernel(nNewKernelSize, bSeparable, padfNewCoefs);

CPLFree(padfNewCoefs);
CSLDestroy(papszCoefItems);

SetNormalized(atoi(CPLGetXMLValue(psTree, "Kernel.normalized", "0")));
adfNewCoefs.push_back(CPLAtof(aosCoefItems[i]));

const CPLErr eErr = SetKernel(nNewKernelSize, bSeparable, adfNewCoefs);
if (eErr == CE_None)
{
SetNormalized(atoi(CPLGetXMLValue(psTree, "Kernel.normalized", "0")) !=
0);
}
return eErr;
}

Expand All @@ -673,29 +660,19 @@ CPLXMLNode *VRTKernelFilteredSource::SerializeToXML(const char *pszVRTPath)

CPLXMLNode *psKernel = CPLCreateXMLNode(psSrc, CXT_Element, "Kernel");

if (m_bNormalized)
CPLCreateXMLNode(
CPLCreateXMLNode(psKernel, CXT_Attribute, "normalized"), CXT_Text,
"1");
else
CPLCreateXMLNode(
CPLCreateXMLNode(psKernel, CXT_Attribute, "normalized"), CXT_Text,
"0");

const int nCoefCount = m_nKernelSize * m_nKernelSize;
const size_t nBufLen = nCoefCount * 32;
char *pszKernelCoefs = static_cast<char *>(CPLMalloc(nBufLen));

strcpy(pszKernelCoefs, "");
for (int iCoef = 0; iCoef < nCoefCount; iCoef++)
CPLsnprintf(pszKernelCoefs + strlen(pszKernelCoefs),
nBufLen - strlen(pszKernelCoefs), "%.8g ",
m_padfKernelCoefs[iCoef]);
CPLCreateXMLNode(CPLCreateXMLNode(psKernel, CXT_Attribute, "normalized"),
CXT_Text, m_bNormalized ? "1" : "0");

CPLSetXMLValue(psKernel, "Size", CPLSPrintf("%d", m_nKernelSize));
CPLSetXMLValue(psKernel, "Coefs", pszKernelCoefs);
std::string osCoefs;
for (auto dfVal : m_adfKernelCoefs)
{
if (!osCoefs.empty())
osCoefs += ' ';
osCoefs += CPLSPrintf("%.8g", dfVal);
}

CPLFree(pszKernelCoefs);
CPLSetXMLValue(psKernel, "Size", CPLSPrintf("%d", m_nKernelSize));
CPLSetXMLValue(psKernel, "Coefs", osCoefs.c_str());

return psSrc;
}
Expand Down
Loading