Skip to content

Commit 1f1dd7d

Browse files
committed
[FEATURE] Extract projection tool for GdalTools
1 parent b35e075 commit 1f1dd7d

File tree

5 files changed

+321
-1
lines changed

5 files changed

+321
-1
lines changed

python/plugins/GdalTools/GdalTools.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,11 @@ def initGui( self ):
115115
self.projection.setStatusTip( QCoreApplication.translate( "GdalTools", "Add projection info to the raster" ) )
116116
QObject.connect( self.projection, SIGNAL( "triggered()" ), self.doProjection )
117117

118-
self.projectionsMenu.addActions( [ self.warp, self.projection ] )
118+
self.extractProj = QAction( QIcon( ":icons/extract-projection.png" ), QCoreApplication.translate( "GdalTools", "Extract projection" ), self.iface.mainWindow() )
119+
self.extractProj.setStatusTip( QCoreApplication.translate( "GdalTools", "Extract projection information from raster(s)" ) )
120+
QObject.connect( self.extractProj, SIGNAL( "triggered()" ), self.doExtractProj )
121+
122+
self.projectionsMenu.addActions( [ self.warp, self.projection, self.extractProj ] )
119123

120124
# conversion menu (Rasterize (Vector to raster), Polygonize (Raster to vector), Translate, RGB to PCT, PCT to RGB)
121125
self.conversionMenu = QMenu( QCoreApplication.translate( "GdalTools", "Conversion" ) )
@@ -341,6 +345,11 @@ def doTileIndex( self ):
341345
d = TileIndex( self.iface )
342346
self.runToolDialog( d )
343347

348+
def doExtractProj( self ):
349+
from tools.doExtractProj import GdalToolsDialog as ExtractProj
350+
d = ExtractProj( self.iface )
351+
d.exec_()
352+
344353
def doDEM( self ):
345354
from tools.doDEM import GdalToolsDialog as DEM
346355
d = DEM( self.iface )
Loading

python/plugins/GdalTools/resources.qrc

+1
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@
2020
<file>icons/tileindex.png</file>
2121
<file>icons/about.png</file>
2222
<file>icons/dem.png</file>
23+
<file>icons/extract-projection.png</file>
2324
</qresource>
2425
</RCC>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>GdalToolsDialog</class>
4+
<widget class="QDialog" name="GdalToolsDialog">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>400</width>
10+
<height>192</height>
11+
</rect>
12+
</property>
13+
<property name="windowTitle">
14+
<string>Extract projection</string>
15+
</property>
16+
<layout class="QVBoxLayout" name="verticalLayout">
17+
<item>
18+
<widget class="QCheckBox" name="batchCheck">
19+
<property name="text">
20+
<string>Batch mode (for processing whole directory)</string>
21+
</property>
22+
</widget>
23+
</item>
24+
<item>
25+
<layout class="QHBoxLayout" name="horizontalLayout">
26+
<item>
27+
<widget class="QLabel" name="label">
28+
<property name="text">
29+
<string>&amp;Input file</string>
30+
</property>
31+
<property name="buddy">
32+
<cstring>inSelector</cstring>
33+
</property>
34+
</widget>
35+
</item>
36+
<item>
37+
<widget class="GdalToolsInOutSelector" name="inSelector" native="true"/>
38+
</item>
39+
</layout>
40+
</item>
41+
<item>
42+
<widget class="QCheckBox" name="recurseCheck">
43+
<property name="text">
44+
<string>Recurse subdirectories</string>
45+
</property>
46+
</widget>
47+
</item>
48+
<item>
49+
<widget class="QCheckBox" name="prjCheck">
50+
<property name="text">
51+
<string>Create also prj file</string>
52+
</property>
53+
</widget>
54+
</item>
55+
<item>
56+
<widget class="QProgressBar" name="progressBar">
57+
<property name="value">
58+
<number>0</number>
59+
</property>
60+
</widget>
61+
</item>
62+
<item>
63+
<widget class="QDialogButtonBox" name="buttonBox">
64+
<property name="orientation">
65+
<enum>Qt::Horizontal</enum>
66+
</property>
67+
<property name="standardButtons">
68+
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
69+
</property>
70+
</widget>
71+
</item>
72+
</layout>
73+
</widget>
74+
<customwidgets>
75+
<customwidget>
76+
<class>GdalToolsInOutSelector</class>
77+
<extends>QWidget</extends>
78+
<header>inOutSelector</header>
79+
<container>1</container>
80+
</customwidget>
81+
</customwidgets>
82+
<resources/>
83+
<connections>
84+
<connection>
85+
<sender>buttonBox</sender>
86+
<signal>accepted()</signal>
87+
<receiver>GdalToolsDialog</receiver>
88+
<slot>accept()</slot>
89+
<hints>
90+
<hint type="sourcelabel">
91+
<x>248</x>
92+
<y>254</y>
93+
</hint>
94+
<hint type="destinationlabel">
95+
<x>157</x>
96+
<y>274</y>
97+
</hint>
98+
</hints>
99+
</connection>
100+
<connection>
101+
<sender>buttonBox</sender>
102+
<signal>rejected()</signal>
103+
<receiver>GdalToolsDialog</receiver>
104+
<slot>reject()</slot>
105+
<hints>
106+
<hint type="sourcelabel">
107+
<x>316</x>
108+
<y>260</y>
109+
</hint>
110+
<hint type="destinationlabel">
111+
<x>286</x>
112+
<y>274</y>
113+
</hint>
114+
</hints>
115+
</connection>
116+
</connections>
117+
</ui>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
# -*- coding: utf-8 -*-
2+
from PyQt4.QtCore import *
3+
from PyQt4.QtGui import *
4+
from qgis.core import *
5+
from qgis.gui import *
6+
7+
from ui_dialogExtractProjection import Ui_GdalToolsDialog as Ui_Dialog
8+
import GdalTools_utils as Utils
9+
10+
import os.path
11+
12+
try:
13+
from osgeo import gdal
14+
from osgeo import osr
15+
except ImportError, e:
16+
error_str = e.args[ 0 ]
17+
error_mod = error_str.replace( "No module named ", "" )
18+
if req_mods.has_key( error_mod ):
19+
error_str = error_str.replace( error_mod, req_mods[error_mod] )
20+
raise ImportError( error_str )
21+
22+
class GdalToolsDialog( QDialog, Ui_Dialog ):
23+
def __init__( self, iface ):
24+
QDialog.__init__( self )
25+
self.setupUi( self )
26+
self.iface = iface
27+
28+
self.inSelector.setType( self.inSelector.FILE )
29+
30+
self.recurseCheck.hide()
31+
32+
self.okButton = self.buttonBox.button( QDialogButtonBox.Ok )
33+
self.cancelButton = self.buttonBox.button( QDialogButtonBox.Cancel )
34+
35+
self.connect( self.inSelector, SIGNAL( "selectClicked()" ), self.fillInputFileEdit )
36+
self.connect( self.batchCheck, SIGNAL( "stateChanged( int )" ), self.switchToolMode )
37+
38+
def switchToolMode( self ):
39+
self.recurseCheck.setVisible( self.batchCheck.isChecked() )
40+
41+
self.inSelector.clear()
42+
43+
if self.batchCheck.isChecked():
44+
self.inFileLabel = self.label.text()
45+
self.label.setText( QCoreApplication.translate( "GdalTools", "&Input directory" ) )
46+
47+
QObject.disconnect( self.inSelector, SIGNAL( "selectClicked()" ), self.fillInputFileEdit )
48+
QObject.connect( self.inSelector, SIGNAL( "selectClicked()" ), self.fillInputDir )
49+
else:
50+
self.label.setText( self.inFileLabel )
51+
52+
QObject.connect( self.inSelector, SIGNAL( "selectClicked()" ), self.fillInputFileEdit )
53+
QObject.disconnect( self.inSelector, SIGNAL( "selectClicked()" ), self.fillInputDir )
54+
55+
def fillInputFileEdit( self ):
56+
lastUsedFilter = Utils.FileFilter.lastUsedRasterFilter()
57+
inputFile = Utils.FileDialog.getOpenFileName( self, self.tr( "Select the file to analyse" ), Utils.FileFilter.allRastersFilter(), lastUsedFilter )
58+
if inputFile.isEmpty():
59+
return
60+
Utils.FileFilter.setLastUsedRasterFilter( lastUsedFilter )
61+
self.inSelector.setFilename( inputFile )
62+
63+
def fillInputDir( self ):
64+
inputDir = Utils.FileDialog.getExistingDirectory( self, self.tr( "Select the input directory with files to Assign projection" ))
65+
if inputDir.isEmpty():
66+
return
67+
self.inSelector.setFilename( inputDir )
68+
69+
def reject( self ):
70+
QDialog.reject( self )
71+
72+
def accept( self ):
73+
self.inFiles = None
74+
if self.batchCheck.isChecked():
75+
self.inFiles = Utils.getRasterFiles( self.inSelector.filename(), self.recurseCheck.isChecked() )
76+
else:
77+
self.inFiles = [ self.inSelector.filename() ]
78+
79+
self.progressBar.setRange( 0, len( self.inFiles ) )
80+
81+
QApplication.setOverrideCursor( QCursor( Qt.WaitCursor ) )
82+
self.okButton.setEnabled( False )
83+
84+
self.extractor = ExtractThread( self.inFiles, self.prjCheck.isChecked() )
85+
QObject.connect( self.extractor, SIGNAL( "fileProcessed()" ), self.updateProgress )
86+
QObject.connect( self.extractor, SIGNAL( "processFinished()" ), self.processingFinished )
87+
QObject.connect( self.extractor, SIGNAL( "processInterrupted()" ), self.processingInterrupted )
88+
89+
QObject.disconnect( self.buttonBox, SIGNAL( "rejected()" ), self.reject )
90+
QObject.connect( self.buttonBox, SIGNAL( "rejected()" ), self.stopProcessing )
91+
92+
self.extractor.start()
93+
94+
def updateProgress( self ):
95+
self.progressBar.setValue( self.progressBar.value() + 1 )
96+
97+
def processingFinished( self ):
98+
self.stopProcessing()
99+
100+
def processingInterrupted( self ):
101+
self.restoreGui()
102+
103+
def stopProcessing( self ):
104+
if self.extractor != None:
105+
self.extractor.stop()
106+
self.extractor = None
107+
108+
self.restoreGui()
109+
110+
def restoreGui( self ):
111+
self.progressBar.setRange( 0, 100 )
112+
self.progressBar.setValue( 0 )
113+
114+
QApplication.restoreOverrideCursor()
115+
116+
QObject.disconnect( self.buttonBox, SIGNAL( "rejected()" ), self.stopProcessing )
117+
QObject.connect( self.buttonBox, SIGNAL( "rejected()" ), self.reject )
118+
119+
self.okButton.setEnabled( True )
120+
121+
# ----------------------------------------------------------------------
122+
123+
def extractProjection( filename, createPrj ):
124+
raster = gdal.Open( unicode( filename ) )
125+
126+
crs = raster.GetProjection()
127+
geotransform = raster.GetGeoTransform()
128+
129+
raster = None
130+
131+
outFileName = os.path.splitext( unicode( filename ) )[0]
132+
133+
# create prj file requested and if projection available
134+
if crs != "" and createPrj:
135+
# convert CRS into ESRI format
136+
tmp = osr.SpatialReference()
137+
tmp.ImportFromWkt( crs )
138+
tmp.MorphToESRI()
139+
crs = tmp.ExportToWkt()
140+
tmp = None
141+
142+
prj = open( outFileName + '.prj', 'wt' )
143+
prj.write( crs )
144+
prj.close()
145+
146+
# create wld file
147+
wld = open( outFileName + '.wld', 'wt')
148+
wld.write( "%0.8f\n" % geotransform[1] )
149+
wld.write( "%0.8f\n" % geotransform[2] )
150+
wld.write( "%0.8f\n" % geotransform[4] )
151+
wld.write( "%0.8f\n" % geotransform[5] )
152+
wld.write( "%0.8f\n" % geotransform[0] )
153+
wld.write( "%0.8f\n" % geotransform[3] )
154+
wld.close()
155+
156+
class ExtractThread( QThread ):
157+
def __init__( self, files, needPrj ):
158+
QThread.__init__( self, QThread.currentThread() )
159+
self.inFiles = files
160+
self.needPrj = needPrj
161+
162+
self.mutex = QMutex()
163+
self.stopMe = 0
164+
165+
def run( self ):
166+
self.mutex.lock()
167+
self.stopMe = 0
168+
self.mutex.unlock()
169+
170+
interrupted = False
171+
172+
for f in self.inFiles:
173+
extractProjection( f, self.needPrj )
174+
self.emit( SIGNAL( "fileProcessed()" ) )
175+
176+
self.mutex.lock()
177+
s = self.stopMe
178+
self.mutex.unlock()
179+
if s == 1:
180+
interrupted = True
181+
break
182+
183+
if not interrupted:
184+
self.emit( SIGNAL( "processFinished()" ) )
185+
else:
186+
self.emit( SIGNAL( "processIterrupted()" ) )
187+
188+
def stop( self ):
189+
self.mutex.lock()
190+
self.stopMe = 1
191+
self.mutex.unlock()
192+
193+
QThread.wait( self )

0 commit comments

Comments
 (0)