Skip to content

Commit b7a47ca

Browse files
author
mmassing
committedFeb 23, 2010
Georeferencer: Implement resampling with user-specified target resolution (enhancement request #2447).
git-svn-id: http://svn.osgeo.org/qgis/trunk@12965 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent e078544 commit b7a47ca

11 files changed

+273
-280
lines changed
 

‎src/plugins/georeferencer/qgsgeorefplugingui.cpp

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ bool QgsGeorefPluginGui::getTransformSettings()
264264
}
265265

266266
d.getTransformSettings(mTransformParam, mResamplingMethod, mCompressionMethod,
267-
mModifiedRasterFileName, mProjection, mUseZeroForTrans, mLoadInQgis);
267+
mModifiedRasterFileName, mProjection, mUseZeroForTrans, mLoadInQgis, mUserResX, mUserResY);
268268
mTransformParamLabel->setText(tr("Transform: ") + convertTransformEnumToString(mTransformParam));
269269
mGeorefTransform.selectTransformParametrisation(mTransformParam);
270270
mGCPListWidget->setGeorefTransform(&mGeorefTransform);
@@ -300,9 +300,12 @@ void QgsGeorefPluginGui::generateGDALScript()
300300
QString gdalwarpCommand;
301301
QString resamplingStr = convertResamplingEnumToString(mResamplingMethod);
302302
if (QgsGeorefTransform::ThinPlateSpline == mTransformParam)
303-
gdalwarpCommand = gdalwarpCommandTPS(resamplingStr, mCompressionMethod, mUseZeroForTrans);
303+
gdalwarpCommand = gdalwarpCommandTPS(resamplingStr, mCompressionMethod, mUseZeroForTrans,
304+
mUserResX, mUserResY);
304305
else
305-
gdalwarpCommand = gdalwarpCommandGCP(resamplingStr, mCompressionMethod, mUseZeroForTrans, polynomeOrder(mTransformParam));
306+
gdalwarpCommand = gdalwarpCommandGCP(resamplingStr, mCompressionMethod, mUseZeroForTrans,
307+
polynomeOrder(mTransformParam),
308+
mUserResX, mUserResY);
306309

307310
showGDALScript(2, gdal_translateCommand().toAscii().data(), gdalwarpCommand.toAscii().data());
308311
}
@@ -1072,7 +1075,7 @@ bool QgsGeorefPluginGui::georeference()
10721075
{
10731076
QgsImageWarper warper(this);
10741077
int res = warper.warpFile( mRasterFileName, mModifiedRasterFileName, mGeorefTransform,
1075-
mResamplingMethod, mUseZeroForTrans, mCompressionMethod, mProjection);
1078+
mResamplingMethod, mUseZeroForTrans, mCompressionMethod, mProjection, mUserResX, mUserResY);
10761079
if (res == 0) // fault to compute GCP transform
10771080
{
10781081
//TODO: be more specific in the error message
@@ -1177,22 +1180,36 @@ QString QgsGeorefPluginGui::gdal_translateCommand(bool generateTFW)
11771180
}
11781181

11791182
QString QgsGeorefPluginGui::gdalwarpCommandGCP(QString resampling, QString compress,
1180-
bool useZeroForTrans, int order)
1183+
bool useZeroForTrans, int order,
1184+
double targetResX, double targetResY)
11811185
{
11821186
QStringList gdalCommand;
11831187
gdalCommand << "gdalwarp" << "-r" << resampling << "-order" << QString::number(order)
1184-
<< "-co COMPRESS" << compress << (useZeroForTrans ? "-dstalpha" : "")
1185-
<< mTranslatedRasterFileName << mModifiedRasterFileName;
1188+
<< "-co COMPRESS="+compress << (useZeroForTrans ? "-dstalpha" : "");
1189+
1190+
if (targetResX != 0.0 && targetResY != 0.0)
1191+
{
1192+
gdalCommand << "-tr" << QString::number(targetResX, 'f') << QString::number(targetResY, 'f');
1193+
}
1194+
1195+
gdalCommand << mTranslatedRasterFileName << mModifiedRasterFileName;
11861196

11871197
return gdalCommand.join(" ");
11881198
}
11891199

1190-
QString QgsGeorefPluginGui::gdalwarpCommandTPS(QString resampling, QString compress, bool useZeroForTrans)
1200+
QString QgsGeorefPluginGui::gdalwarpCommandTPS(QString resampling, QString compress, bool useZeroForTrans,
1201+
double targetResX, double targetResY)
11911202
{
11921203
QStringList gdalCommand;
11931204
gdalCommand << "gdalwarp" << "-r" << resampling << "-tps"
1194-
<< "-co COMPRESS" << compress << (useZeroForTrans ? "-dstalpha" : "")
1195-
<< mTranslatedRasterFileName << mModifiedRasterFileName;
1205+
<< "-co COMPRESS="+compress << (useZeroForTrans ? "-dstalpha" : "");
1206+
1207+
if (targetResX != 0.0 && targetResY != 0.0)
1208+
{
1209+
gdalCommand << "-tr" << QString::number(targetResX, 'f') << QString::number(targetResY, 'f');
1210+
}
1211+
1212+
gdalCommand << mTranslatedRasterFileName << mModifiedRasterFileName;
11961213

11971214
return gdalCommand.join(" ");
11981215
}

‎src/plugins/georeferencer/qgsgeorefplugingui.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,10 @@ private slots:
136136
// gdal script
137137
void showGDALScript(int argNum...);
138138
QString gdal_translateCommand(bool generateTFW = true);
139-
QString gdalwarpCommandGCP(QString resampling, QString compress, bool useZeroForTrans,
140-
int order);
141-
QString gdalwarpCommandTPS(QString resampling, QString compress, bool useZeroForTrans);
139+
QString gdalwarpCommandGCP(QString resampling, QString compress, bool useZeroForTrans, int order,
140+
double targetResX, double targetResY);
141+
QString gdalwarpCommandTPS(QString resampling, QString compress, bool useZeroForTrans,
142+
double targetResX, double targetResY);
142143

143144
// log
144145
void showMessageInLog(const QString &description, const QString &msg);
@@ -180,6 +181,7 @@ private slots:
180181
QString mTranslatedRasterFileName;
181182
QString mGCPpointsFileName;
182183
QString mProjection;
184+
double mUserResX, mUserResY; // User specified target scale
183185

184186
QgsGeorefTransform::TransformParametrisation mTransformParam;
185187
QgsImageWarper::ResamplingMethod mResamplingMethod;

‎src/plugins/georeferencer/qgsgeorefwarpoptionsdialog.cpp

Lines changed: 0 additions & 68 deletions
This file was deleted.

‎src/plugins/georeferencer/qgsgeorefwarpoptionsdialog.h

Lines changed: 0 additions & 34 deletions
This file was deleted.

‎src/plugins/georeferencer/qgsgeorefwarpoptionsdialogbase.ui

Lines changed: 0 additions & 158 deletions
This file was deleted.

‎src/plugins/georeferencer/qgsimagewarper.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <cmath>
1818
#include <iostream>
1919
#include <cstdio>
20+
#include <assert.h>
2021

2122
#include <cpl_conv.h>
2223
#include <cpl_string.h>
@@ -149,7 +150,8 @@ int QgsImageWarper::warpFile( const QString& input,
149150
ResamplingMethod resampling,
150151
bool useZeroAsTrans,
151152
const QString& compression,
152-
const QString &projection)
153+
const QString &projection,
154+
double destResX, double destResY)
153155
{
154156
if (!georefTransform.parametersInitialized())
155157
return false;
@@ -174,6 +176,35 @@ int QgsImageWarper::warpFile( const QString& input,
174176
GDALDestroyWarpOptions( psWarpOptions );
175177
return false;
176178
}
179+
180+
// If specified, override the suggested resolution with user values
181+
if (destResX != 0.0 || destResY != 0.0)
182+
{
183+
// If only one scale has been specified, fill in the other from the GDAL suggestion
184+
if (destResX == 0.0) destResX = adfGeoTransform[1];
185+
if (destResY == 0.0) destResY = adfGeoTransform[5];
186+
187+
// Make sure user-specified coordinate system has canonical orientation
188+
if (destResX < 0.0) destResX = -destResX;
189+
if (destResY > 0.0) destResY = -destResY;
190+
191+
// Assert that the north-up convention is fullfiled by GDALSuggestedWarpOutput (should always be the case)
192+
assert(adfGeoTransform[0] > 0.0);
193+
assert(adfGeoTransform[5] < 0.0);
194+
// Find suggested output image extent (in georeferenced units)
195+
double minX = adfGeoTransform[0];
196+
double maxX = adfGeoTransform[0] + adfGeoTransform[1]*destPixels;
197+
double maxY = adfGeoTransform[3];
198+
double minY = adfGeoTransform[3] + adfGeoTransform[5]*destLines;
199+
200+
// Update line and pixel count to match extent at user-specified resolution
201+
destPixels = (int)(((maxX - minX) / destResX) + 0.5);
202+
destLines = (int)(((minY - maxY) / destResY) + 0.5);
203+
adfGeoTransform[0] = minX;
204+
adfGeoTransform[3] = maxY;
205+
adfGeoTransform[1] = destResX;
206+
adfGeoTransform[5] = destResY;
207+
}
177208

178209
if (!createDestinationDataset(output, hSrcDS, hDstDS, destPixels, destLines,
179210
adfGeoTransform, useZeroAsTrans, compression,

‎src/plugins/georeferencer/qgsimagewarper.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,22 @@ class QgsImageWarper
4343
Lanczos = GRA_Lanczos
4444
};
4545

46+
/**
47+
* Warp the file specified by "input" and write the resulting raster to the file "output".
48+
* \param georefTransform Specified the warp transformation which should be applied to "input".
49+
* \param resampling Specifies image resampling algorithm to use.
50+
* \param useZeroAsTrans Specifies whether to mark transparent areas with a value of "zero".
51+
* \param destResX The desired horizontal resolution of the output file, in target georeferenced units. A value of zero means automatic selection.
52+
* \param destResY The desired vertical resolution of the output file, in target georeferenced units. A value of zero means automatic selection.
53+
*/
4654
int warpFile( const QString& input,
4755
const QString& output,
4856
const QgsGeorefTransform &georefTransform,
4957
ResamplingMethod resampling,
5058
bool useZeroAsTrans,
5159
const QString& compression,
52-
const QString &projection);
60+
const QString& projection,
61+
double destResX = 0.0, double destResY = 0.0);
5362
private:
5463
struct TransformChain {
5564
GDALTransformerFunc GDALTransformer;

‎src/plugins/georeferencer/qgstransformsettingsdialog.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,22 @@ QgsTransformSettingsDialog::QgsTransformSettingsDialog(const QString &raster, co
5050
cmbResampling->setCurrentIndex(s.value("/Plugin-GeoReferencer/lastresampling", 0).toInt());
5151
cmbCompressionComboBox->setCurrentIndex(s.value("/Plugin-GeoReferencer/lastcompression", 0).toInt());
5252
leTargetSRS->setText(s.value("/Plugin-GeoReferencer/targetsrs").toString());
53+
54+
cbxUserResolution->setChecked(s.value("/Plugin-Georeferencer/user_specified_resolution", false).toBool());
55+
bool ok;
56+
dsbHorizRes->setValue(s.value("/Plugin-GeoReferencer/user_specified_resx", 1.0).toDouble(&ok));
57+
if (!ok) dsbHorizRes->setValue( 1.0);
58+
dsbVerticalRes->setValue(s.value("/Plugin-GeoReferencer/user_specified_resy", -1.0).toDouble(&ok));
59+
if (!ok) dsbHorizRes->setValue(-1.0);
60+
// Activate spin boxes for vertical/horizontal resolution, if the option is checked
61+
dsbHorizRes->setEnabled(cbxUserResolution->isChecked());
62+
dsbVerticalRes->setEnabled(cbxUserResolution->isChecked());
63+
// Update activation of spinboxes, if the user specified resolution is checked/unchecked
64+
connect( cbxUserResolution, SIGNAL( toggled( bool ) ), dsbHorizRes, SLOT( setEnabled( bool ) ) );
65+
connect( cbxUserResolution, SIGNAL( toggled( bool ) ), dsbVerticalRes, SLOT( setEnabled( bool ) ) );
66+
5367
cbxZeroAsTrans->setChecked(s.value("/Plugin-GeoReferencer/zeroastrans", false).toBool());
54-
cbxLoadInQgisWhenDone->setChecked(s.value("/Plugin-GeoReferencer/loadinqgis", false).toBool());;;
68+
cbxLoadInQgisWhenDone->setChecked(s.value("/Plugin-GeoReferencer/loadinqgis", false).toBool());
5569

5670
tbnOutputRaster->setIcon(getThemeIcon("/mPushButtonFileOpen.png"));
5771
tbnTargetSRS->setIcon(getThemeIcon("/mPushButtonTargetSRSDisabled.png"));
@@ -60,7 +74,8 @@ QgsTransformSettingsDialog::QgsTransformSettingsDialog(const QString &raster, co
6074
void QgsTransformSettingsDialog::getTransformSettings(QgsGeorefTransform::TransformParametrisation &tp,
6175
QgsImageWarper::ResamplingMethod &rm,
6276
QString &comprMethod, QString &raster,
63-
QString &proj, bool &zt, bool &loadInQgis)
77+
QString &proj, bool &zt, bool &loadInQgis,
78+
double& resX, double& resY)
6479
{
6580
if (cmbTransformType->currentIndex() == -1)
6681
tp = QgsGeorefTransform::InvalidTransform;
@@ -73,6 +88,13 @@ void QgsTransformSettingsDialog::getTransformSettings(QgsGeorefTransform::Transf
7388
proj = leTargetSRS->text();
7489
zt = cbxZeroAsTrans->isChecked();
7590
loadInQgis = cbxLoadInQgisWhenDone->isChecked();
91+
resX = 0.0;
92+
resY = 0.0;
93+
if (cbxUserResolution->isChecked())
94+
{
95+
resX = dsbHorizRes->value();
96+
resY = dsbVerticalRes->value();
97+
}
7698
}
7799

78100
void QgsTransformSettingsDialog::resetSettings()
@@ -84,6 +106,9 @@ void QgsTransformSettingsDialog::resetSettings()
84106
s.setValue("/Plugin-GeoReferencer/targetsrs", QString());
85107
s.setValue("/Plugin-GeoReferencer/zeroastrans", false);
86108
s.setValue("/Plugin-GeoReferencer/loadinqgis", false);
109+
s.setValue("/Plugin-GeoReferencer/user_specified_resolution", false);
110+
s.setValue("/Plugin-GeoReferencer/user_specified_resx", 1.0);
111+
s.setValue("/Plugin-GeoReferencer/user_specified_resy", -1.0);
87112
}
88113

89114
void QgsTransformSettingsDialog::changeEvent(QEvent *e)
@@ -126,6 +151,9 @@ void QgsTransformSettingsDialog::accept()
126151
s.setValue("/Plugin-GeoReferencer/targetsrs", leTargetSRS->text());
127152
s.setValue("/Plugin-GeoReferencer/zeroastrans", cbxZeroAsTrans->isChecked());
128153
s.setValue("/Plugin-GeoReferencer/loadinqgis", cbxLoadInQgisWhenDone->isChecked());
154+
s.setValue("/Plugin-GeoReferencer/user_specified_resolution", cbxUserResolution->isChecked());
155+
s.setValue("/Plugin-GeoReferencer/user_specified_resx", dsbHorizRes->value());
156+
s.setValue("/Plugin-GeoReferencer/user_specified_resy", dsbVerticalRes->value());
129157
}
130158

131159
void QgsTransformSettingsDialog::on_tbnOutputRaster_clicked()

‎src/plugins/georeferencer/qgstransformsettingsdialog.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ class QgsTransformSettingsDialog : public QDialog, private Ui::QgsTransformSetti
3232
int countGCPpoints, QWidget *parent = 0);
3333
void getTransformSettings(QgsGeorefTransform::TransformParametrisation &tp,
3434
QgsImageWarper::ResamplingMethod &rm, QString &comprMethod,
35-
QString &raster, QString &proj, bool &zt, bool &loadInQgis);
35+
QString &raster, QString &proj, bool &zt, bool &loadInQgis,
36+
double& resX, double& resY);
3637
static void resetSettings();
3738

3839
protected:

‎src/plugins/georeferencer/qgstransformsettingsdialogbase.ui

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
<rect>
77
<x>0</x>
88
<y>0</y>
9-
<width>312</width>
10-
<height>249</height>
9+
<width>307</width>
10+
<height>328</height>
1111
</rect>
1212
</property>
1313
<property name="windowTitle">
@@ -16,6 +16,9 @@
1616
<layout class="QVBoxLayout" name="verticalLayout">
1717
<item>
1818
<layout class="QFormLayout" name="formLayout">
19+
<property name="fieldGrowthPolicy">
20+
<enum>QFormLayout::ExpandingFieldsGrow</enum>
21+
</property>
1922
<item row="0" column="0">
2023
<widget class="QLabel" name="label">
2124
<property name="text">
@@ -157,6 +160,62 @@
157160
</item>
158161
</layout>
159162
</item>
163+
<item row="5" column="0">
164+
<widget class="QCheckBox" name="cbxUserResolution">
165+
<property name="text">
166+
<string>Set Target Resolution</string>
167+
</property>
168+
</widget>
169+
</item>
170+
<item row="6" column="0">
171+
<widget class="QLabel" name="label_4">
172+
<property name="text">
173+
<string>Horizontal</string>
174+
</property>
175+
</widget>
176+
</item>
177+
<item row="7" column="0">
178+
<widget class="QLabel" name="label_5">
179+
<property name="text">
180+
<string>Vertical</string>
181+
</property>
182+
</widget>
183+
</item>
184+
<item row="7" column="1">
185+
<widget class="QgsValidatedDoubleSpinBox" name="dsbVerticalRes">
186+
<property name="sizePolicy">
187+
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
188+
<horstretch>0</horstretch>
189+
<verstretch>0</verstretch>
190+
</sizepolicy>
191+
</property>
192+
<property name="frame">
193+
<bool>true</bool>
194+
</property>
195+
<property name="decimals">
196+
<number>5</number>
197+
</property>
198+
<property name="minimum">
199+
<double>-999999.000000000000000</double>
200+
</property>
201+
<property name="maximum">
202+
<double>0.000000000000000</double>
203+
</property>
204+
</widget>
205+
</item>
206+
<item row="6" column="1">
207+
<widget class="QgsValidatedDoubleSpinBox" name="dsbHorizRes">
208+
<property name="decimals">
209+
<number>5</number>
210+
</property>
211+
<property name="minimum">
212+
<double>0.000000000000000</double>
213+
</property>
214+
<property name="maximum">
215+
<double>999999.000000000000000</double>
216+
</property>
217+
</widget>
218+
</item>
160219
</layout>
161220
</item>
162221
<item>
@@ -188,6 +247,28 @@
188247
</item>
189248
</layout>
190249
</widget>
250+
<customwidgets>
251+
<customwidget>
252+
<class>QgsValidatedDoubleSpinBox</class>
253+
<extends>QDoubleSpinBox</extends>
254+
<header>qgsvalidateddoublespinbox.h</header>
255+
</customwidget>
256+
</customwidgets>
257+
<tabstops>
258+
<tabstop>cmbTransformType</tabstop>
259+
<tabstop>cmbResampling</tabstop>
260+
<tabstop>cmbCompressionComboBox</tabstop>
261+
<tabstop>leOutputRaster</tabstop>
262+
<tabstop>tbnOutputRaster</tabstop>
263+
<tabstop>leTargetSRS</tabstop>
264+
<tabstop>tbnTargetSRS</tabstop>
265+
<tabstop>cbxUserResolution</tabstop>
266+
<tabstop>dsbHorizRes</tabstop>
267+
<tabstop>dsbVerticalRes</tabstop>
268+
<tabstop>cbxZeroAsTrans</tabstop>
269+
<tabstop>cbxLoadInQgisWhenDone</tabstop>
270+
<tabstop>buttonBox</tabstop>
271+
</tabstops>
191272
<resources/>
192273
<connections>
193274
<connection>
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/***************************************************************************
2+
qgsvalidateddoublespinbox.h - Simple extension to QDoubleSpinBox which
3+
implements a validate function to disallow zero as input.
4+
--------------------------------------
5+
Date : 23-Feb-2010
6+
Copyright : (c) 2010 by Manuel Massing
7+
Email : m.massing at warped-space.de
8+
***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
/* $Id */
17+
18+
#ifndef QGS_VALIDATED_DOUBLE_SPINBOX_H
19+
#define QGS_VALIDATED_DOUBLE_SPINBOX_H
20+
21+
#include <QDoubleSpinBox>
22+
23+
class QgsValidatedDoubleSpinBox : public QDoubleSpinBox {
24+
public:
25+
QgsValidatedDoubleSpinBox(QWidget *widget) : QDoubleSpinBox(widget) { }
26+
27+
QValidator::State validate(QString& input, int& pos ) const
28+
{
29+
QValidator::State state = QDoubleSpinBox::validate(input ,pos);
30+
if (state != QValidator::Acceptable)
31+
{
32+
return state;
33+
}
34+
35+
// A value of zero is acceptable as intermediate result,
36+
// but not as final entry
37+
double val = valueFromText(input);
38+
if (val == 0.0)
39+
{
40+
return QValidator::Intermediate;
41+
}
42+
return QValidator::Acceptable;
43+
}
44+
45+
StepEnabled stepEnabled () const
46+
{
47+
StepEnabled mayStep = StepNone;
48+
49+
// Zero is off limits, so handle the logic differently
50+
// (always exclude zero from the permitted interval)
51+
if (minimum() == 0.0)
52+
{
53+
if (value() - singleStep() > minimum())
54+
{
55+
mayStep|= StepDownEnabled;
56+
}
57+
}
58+
else // closed interval
59+
{
60+
if (value() - singleStep() >= minimum())
61+
{
62+
mayStep|= StepDownEnabled;
63+
}
64+
}
65+
66+
if (maximum() == 0.0)
67+
{
68+
if (value() + singleStep() < maximum())
69+
{
70+
mayStep|= StepUpEnabled;
71+
}
72+
}
73+
else
74+
{
75+
if (value() + singleStep() <= maximum())
76+
{
77+
mayStep|= StepUpEnabled;
78+
}
79+
}
80+
return mayStep;
81+
}
82+
};
83+
84+
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.