mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
[FEATURE] Implement saving paletted raster renderer color tables
Use the .clr/gdal file format, but add the labels on the ends of the lines. Seems other importers like ArcMap just ignore these.
This commit is contained in:
parent
d0566f7792
commit
7eb63d99dc
@ -39,6 +39,7 @@ class QgsPalettedRasterRenderer : QgsRasterRenderer
|
||||
static QgsPalettedRasterRenderer::ClassData colorTableToClassData( const QList<QgsColorRampShader::ColorRampItem> &table );
|
||||
static QgsPalettedRasterRenderer::ClassData classDataFromString( const QString &string );
|
||||
static QgsPalettedRasterRenderer::ClassData classDataFromFile( const QString &path );
|
||||
static QString classDataToString( const QgsPalettedRasterRenderer::ClassData &classes );
|
||||
|
||||
private:
|
||||
|
||||
|
@ -326,9 +326,11 @@ QgsPalettedRasterRenderer::ClassData QgsPalettedRasterRenderer::classDataFromStr
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
case 5:
|
||||
default:
|
||||
{
|
||||
if ( lineParts.count() < 4 )
|
||||
continue;
|
||||
|
||||
int value = lineParts.at( 0 ).toInt( &ok );
|
||||
if ( !ok )
|
||||
continue;
|
||||
@ -346,14 +348,20 @@ QgsPalettedRasterRenderer::ClassData QgsPalettedRasterRenderer::classDataFromStr
|
||||
c = QColor( r, g, b );
|
||||
}
|
||||
|
||||
if ( lineParts.count() == 5 )
|
||||
if ( lineParts.count() >= 5 )
|
||||
{
|
||||
double alpha = lineParts.at( 4 ).toDouble( &ok );
|
||||
if ( ok )
|
||||
c.setAlpha( alpha );
|
||||
}
|
||||
|
||||
classes << Class( value, c );
|
||||
QString label;
|
||||
if ( lineParts.count() > 5 )
|
||||
{
|
||||
label = lineParts.mid( 5 ).join( ' ' );
|
||||
}
|
||||
|
||||
classes << Class( value, c, label );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -375,6 +383,24 @@ QgsPalettedRasterRenderer::ClassData QgsPalettedRasterRenderer::classDataFromFil
|
||||
return classDataFromString( input );
|
||||
}
|
||||
|
||||
QString QgsPalettedRasterRenderer::classDataToString( const QgsPalettedRasterRenderer::ClassData &classes )
|
||||
{
|
||||
QStringList out;
|
||||
// must be sorted
|
||||
QgsPalettedRasterRenderer::ClassData cd = classes;
|
||||
std::sort( cd.begin(), cd.end(), []( const Class & a, const Class & b ) -> bool
|
||||
{
|
||||
return a.value < b.value;
|
||||
} );
|
||||
|
||||
Q_FOREACH ( const Class &c, cd )
|
||||
{
|
||||
out << QString( "%1 %2 %3 %4 %5 %6" ).arg( c.value ).arg( c.color.red() )
|
||||
.arg( c.color.green() ).arg( c.color.blue() ).arg( c.color.alpha() ).arg( c.label );
|
||||
}
|
||||
return out.join( '\n' );
|
||||
}
|
||||
|
||||
void QgsPalettedRasterRenderer::updateArrays()
|
||||
{
|
||||
// find maximum color index
|
||||
|
@ -117,6 +117,7 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer
|
||||
* Converts a \a string containing a color table or class data to to paletted renderer class data.
|
||||
* @note added in QGIS 3.0
|
||||
* @see classDataFromFile()
|
||||
* @see classDataToString()
|
||||
*/
|
||||
static QgsPalettedRasterRenderer::ClassData classDataFromString( const QString &string );
|
||||
|
||||
@ -127,6 +128,13 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer
|
||||
*/
|
||||
static QgsPalettedRasterRenderer::ClassData classDataFromFile( const QString &path );
|
||||
|
||||
/**
|
||||
* Converts classes to a string representation, using the .clr/gdal color table file format.
|
||||
* @note added in QGIS 3.0
|
||||
* @see classDataFromString()
|
||||
*/
|
||||
static QString classDataToString( const QgsPalettedRasterRenderer::ClassData &classes );
|
||||
|
||||
private:
|
||||
|
||||
int mBand;
|
||||
|
@ -92,6 +92,7 @@ QgsPalettedRendererWidget::QgsPalettedRendererWidget( QgsRasterLayer *layer, con
|
||||
connect( mDeleteEntryButton, &QPushButton::clicked, this, &QgsPalettedRendererWidget::deleteEntry );
|
||||
connect( mAddEntryButton, &QPushButton::clicked, this, &QgsPalettedRendererWidget::addEntry );
|
||||
connect( mLoadFromFileButton, &QPushButton::clicked, this, &QgsPalettedRendererWidget::loadColorTable );
|
||||
connect( mExportToFileButton, &QPushButton::clicked, this, &QgsPalettedRendererWidget::saveColorTable );
|
||||
}
|
||||
|
||||
QgsRasterRenderer *QgsPalettedRendererWidget::renderer()
|
||||
@ -336,6 +337,36 @@ void QgsPalettedRendererWidget::loadColorTable()
|
||||
}
|
||||
}
|
||||
|
||||
void QgsPalettedRendererWidget::saveColorTable()
|
||||
{
|
||||
QgsSettings settings;
|
||||
QString lastDir = settings.value( QStringLiteral( "lastColorMapDir" ), QDir::homePath() ).toString();
|
||||
QString fileName = QFileDialog::getSaveFileName( this, tr( "Save file" ), lastDir, tr( "Text (*.clr)" ) );
|
||||
if ( !fileName.isEmpty() )
|
||||
{
|
||||
if ( !fileName.endsWith( QLatin1String( ".clr" ), Qt::CaseInsensitive ) )
|
||||
{
|
||||
fileName = fileName + ".clr";
|
||||
}
|
||||
|
||||
QFile outputFile( fileName );
|
||||
if ( outputFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
|
||||
{
|
||||
QTextStream outputStream( &outputFile );
|
||||
outputStream << QgsPalettedRasterRenderer::classDataToString( mModel->classData() );
|
||||
outputStream.flush();
|
||||
outputFile.close();
|
||||
|
||||
QFileInfo fileInfo( fileName );
|
||||
settings.setValue( QStringLiteral( "lastColorMapDir" ), fileInfo.absoluteDir().absolutePath() );
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning( this, tr( "Write access denied" ), tr( "Write access denied. Adjust the file permissions and try again.\n\n" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// QgsPalettedRendererModel
|
||||
//
|
||||
|
@ -108,6 +108,8 @@ class GUI_EXPORT QgsPalettedRendererWidget: public QgsRasterRendererWidget, priv
|
||||
void changeLabel();
|
||||
void applyColorRamp();
|
||||
void loadColorTable();
|
||||
void saveColorTable();
|
||||
|
||||
};
|
||||
|
||||
#endif // QGSPALETTEDRENDERERWIDGET_H
|
||||
|
@ -480,6 +480,19 @@ class TestQgsRasterLayer(unittest.TestCase):
|
||||
self.assertEqual(classes[4].color.name(), '#0000ff')
|
||||
self.assertEqual(classes[4].color.alpha(), 255)
|
||||
|
||||
# qgis style, with labels
|
||||
qgis = '3 255 0 0 255 class 1\n4 0 255 0 200 class 2'
|
||||
classes = QgsPalettedRasterRenderer.classDataFromString(qgis)
|
||||
self.assertEqual(len(classes), 2)
|
||||
self.assertEqual(classes[0].value, 3)
|
||||
self.assertEqual(classes[0].color.name(), '#ff0000')
|
||||
self.assertEqual(classes[0].color.alpha(), 255)
|
||||
self.assertEqual(classes[0].label, 'class 1')
|
||||
self.assertEqual(classes[1].value, 4)
|
||||
self.assertEqual(classes[1].color.name(), '#00ff00')
|
||||
self.assertEqual(classes[1].color.alpha(), 200)
|
||||
self.assertEqual(classes[1].label, 'class 2')
|
||||
|
||||
# some bad inputs
|
||||
bad = ''
|
||||
classes = QgsPalettedRasterRenderer.classDataFromString(bad)
|
||||
@ -496,9 +509,6 @@ class TestQgsRasterLayer(unittest.TestCase):
|
||||
bad = '1 255 a 0'
|
||||
classes = QgsPalettedRasterRenderer.classDataFromString(bad)
|
||||
self.assertEqual(len(classes), 1)
|
||||
bad = '1 255 255 0 0 0 0 0 0 0'
|
||||
classes = QgsPalettedRasterRenderer.classDataFromString(bad)
|
||||
self.assertEqual(len(classes), 0)
|
||||
|
||||
def testLoadPalettedClassDataFromFile(self):
|
||||
# bad file
|
||||
@ -533,5 +543,16 @@ class TestQgsRasterLayer(unittest.TestCase):
|
||||
self.assertEqual(classes[9].value, 10)
|
||||
self.assertEqual(classes[9].color.name(), '#ffb600')
|
||||
|
||||
def testPalettedClassDataToString(self):
|
||||
classes = [QgsPalettedRasterRenderer.Class(1, QColor(0, 255, 0), 'class 2'),
|
||||
QgsPalettedRasterRenderer.Class(3, QColor(255, 0, 0), 'class 1')]
|
||||
self.assertEqual(QgsPalettedRasterRenderer.classDataToString(classes), '1 0 255 0 255 class 2\n3 255 0 0 255 class 1')
|
||||
# must be sorted by value to work OK in ArcMap
|
||||
classes = [QgsPalettedRasterRenderer.Class(4, QColor(0, 255, 0), 'class 2'),
|
||||
QgsPalettedRasterRenderer.Class(3, QColor(255, 0, 0), 'class 1')]
|
||||
self.assertEqual(QgsPalettedRasterRenderer.classDataToString(classes),
|
||||
'3 255 0 0 255 class 1\n4 0 255 0 255 class 2')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
10
tests/testdata/raster/test.clr
vendored
Normal file
10
tests/testdata/raster/test.clr
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
1 0 0 0
|
||||
2 200 200 200
|
||||
3 0 110 0
|
||||
4 110 65 0
|
||||
5 0 0 255
|
||||
6 0 89 255
|
||||
7 0 174 255
|
||||
8 0 255 246
|
||||
9 238 255 0
|
||||
10 255 182 0
|
Loading…
x
Reference in New Issue
Block a user