File indexing completed on 2024-03-24 03:52:46
0001 // SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <tackat@kde.org> 0002 // SPDX-FileCopyrightText: 2007-2008 Inge Wallin <ingwa@kde.org> 0003 // SPDX-FileCopyrightText: 2011 Niko Sams <niko.sams@gmail.com> 0004 // 0005 // SPDX-License-Identifier: LGPL-2.1-or-later 0006 0007 #include "TileCreator.h" 0008 0009 #include <cmath> 0010 0011 #include <QDir> 0012 #include <QRect> 0013 #include <QSize> 0014 #include <QVector> 0015 #include <QApplication> 0016 #include <QImage> 0017 #include <QPainter> 0018 0019 #include "MarbleGlobal.h" 0020 #include "MarbleDirs.h" 0021 #include "MarbleDebug.h" 0022 #include "TileLoaderHelper.h" 0023 0024 namespace Marble 0025 { 0026 0027 class TileCreatorPrivate 0028 { 0029 public: 0030 TileCreatorPrivate( TileCreatorSource *source, 0031 const QString& dem, const QString& targetDir=QString() ) 0032 : m_dem( dem ), 0033 m_targetDir( targetDir ), 0034 m_cancelled( false ), 0035 m_tileFormat( "jpg" ), 0036 m_resume( false ), 0037 m_verify( false ), 0038 m_source( source ) 0039 { 0040 if (m_dem == QLatin1String("true")) { 0041 m_tileQuality = 70; 0042 } else { 0043 m_tileQuality = 85; 0044 } 0045 } 0046 0047 ~TileCreatorPrivate() 0048 { 0049 delete m_source; 0050 } 0051 0052 public: 0053 QString m_dem; 0054 QString m_targetDir; 0055 bool m_cancelled; 0056 QString m_tileFormat; 0057 int m_tileQuality; 0058 bool m_resume; 0059 bool m_verify; 0060 0061 TileCreatorSource *m_source; 0062 }; 0063 0064 class TileCreatorSourceImage : public TileCreatorSource 0065 { 0066 public: 0067 explicit TileCreatorSourceImage( const QString &sourcePath ) 0068 : m_sourceImage( QImage( sourcePath ) ), 0069 m_cachedRowNum( -1 ) 0070 { 0071 } 0072 0073 QSize fullImageSize() const override 0074 { 0075 if ( m_sourceImage.size().width() > 21600 || m_sourceImage.height() > 10800 ) { 0076 qDebug("Install map too large!"); 0077 return QSize(); 0078 } 0079 return m_sourceImage.size(); 0080 } 0081 0082 QImage tile(int n, int m, int maxTileLevel) override 0083 { 0084 int mmax = TileLoaderHelper::levelToColumn( defaultLevelZeroColumns, maxTileLevel ); 0085 int nmax = TileLoaderHelper::levelToRow( defaultLevelZeroRows, maxTileLevel ); 0086 0087 int imageHeight = m_sourceImage.height(); 0088 int imageWidth = m_sourceImage.width(); 0089 0090 // If the image size of the image source does not match the expected 0091 // geometry we need to smooth-scale the image in advance to match 0092 // the required size 0093 bool needsScaling = ( imageWidth != 2 * nmax * (int)( c_defaultTileSize ) 0094 || imageHeight != nmax * (int)( c_defaultTileSize ) ); 0095 0096 if ( needsScaling ) 0097 mDebug() << "Image Size doesn't match 2*n*TILEWIDTH x n*TILEHEIGHT geometry. Scaling ..."; 0098 0099 int stdImageWidth = 2 * nmax * c_defaultTileSize; 0100 if ( stdImageWidth == 0 ) 0101 stdImageWidth = 2 * c_defaultTileSize; 0102 0103 int stdImageHeight = nmax * c_defaultTileSize; 0104 if ( stdImageWidth != imageWidth ) { 0105 mDebug() << 0106 QString( "TileCreator::createTiles() The size of the final image will measure %1 x %2 pixels").arg(stdImageWidth).arg(stdImageHeight); 0107 } 0108 0109 QImage row; 0110 0111 if ( m_cachedRowNum == n ) { 0112 0113 row = m_rowCache; 0114 0115 } else { 0116 0117 QRect sourceRowRect( 0, (int)( (qreal)( n * imageHeight ) / (qreal)( nmax )), 0118 imageWidth,(int)( (qreal)( imageHeight ) / (qreal)( nmax ) ) ); 0119 0120 0121 row = m_sourceImage.copy( sourceRowRect ); 0122 0123 if ( needsScaling ) { 0124 // Pick the current row and smooth scale it 0125 // to make it match the expected size 0126 QSize destSize( stdImageWidth, c_defaultTileSize ); 0127 row = row.scaled( destSize, 0128 Qt::IgnoreAspectRatio, 0129 Qt::SmoothTransformation ); 0130 } 0131 0132 m_cachedRowNum = n; 0133 m_rowCache = row; 0134 } 0135 0136 if ( row.isNull() ) { 0137 mDebug() << "Read-Error! Null QImage!"; 0138 return QImage(); 0139 } 0140 0141 QImage tile = row.copy( m * stdImageWidth / mmax, 0, c_defaultTileSize, c_defaultTileSize ); 0142 0143 return tile; 0144 } 0145 0146 private: 0147 QImage m_sourceImage; 0148 0149 QImage m_rowCache; 0150 int m_cachedRowNum; 0151 }; 0152 0153 0154 TileCreator::TileCreator(const QString& sourceDir, const QString& installMap, 0155 const QString& dem, const QString& targetDir) 0156 : QThread(nullptr), 0157 d( new TileCreatorPrivate( nullptr, dem, targetDir ) ) 0158 0159 { 0160 mDebug() << "Prefix: " << sourceDir 0161 << "installmap:" << installMap; 0162 0163 QString sourcePath; 0164 0165 // If the sourceDir starts with a '/' assume an absolute path. 0166 // Otherwise assume a relative marble data path 0167 if ( QDir::isAbsolutePath( sourceDir ) ) { 0168 sourcePath = sourceDir + QLatin1Char('/') + installMap; 0169 mDebug() << "Trying absolute path*:" << sourcePath; 0170 } 0171 else { 0172 sourcePath = MarbleDirs::path(QLatin1String("maps/") + sourceDir + QLatin1Char('/') + installMap); 0173 mDebug() << "Trying relative path*:" 0174 << QLatin1String("maps/") + sourceDir + QLatin1Char('/') + installMap; 0175 } 0176 0177 mDebug() << "Creating tiles from*: " << sourcePath; 0178 0179 d->m_source = new TileCreatorSourceImage( sourcePath ); 0180 0181 if ( d->m_targetDir.isNull() ) 0182 d->m_targetDir = MarbleDirs::localPath() + QLatin1String("/maps/") 0183 + sourcePath.section(QLatin1Char('/'), -3, -2) + QLatin1Char('/'); 0184 0185 setTerminationEnabled( true ); 0186 } 0187 0188 TileCreator::TileCreator( TileCreatorSource* source, const QString& dem, const QString& targetDir ) 0189 : QThread(nullptr), 0190 d( new TileCreatorPrivate( source, dem, targetDir ) ) 0191 { 0192 setTerminationEnabled( true ); 0193 } 0194 0195 TileCreator::~TileCreator() 0196 { 0197 delete d; 0198 } 0199 0200 void TileCreator::cancelTileCreation() 0201 { 0202 d->m_cancelled = true; 0203 } 0204 0205 void TileCreator::run() 0206 { 0207 if (d->m_resume && d->m_tileFormat == QLatin1String("jpg") && d->m_tileQuality != 100) { 0208 qWarning() << "Resuming jpegs is only supported with tileQuality 100"; 0209 return; 0210 } 0211 0212 if (!d->m_targetDir.endsWith(QLatin1Char('/'))) 0213 d->m_targetDir += QLatin1Char('/'); 0214 0215 mDebug() << "Installing tiles to: " << d->m_targetDir; 0216 0217 QVector<QRgb> grayScalePalette; 0218 for ( int cnt = 0; cnt <= 255; ++cnt ) { 0219 grayScalePalette.insert(cnt, qRgb(cnt, cnt, cnt)); 0220 } 0221 0222 QSize fullImageSize = d->m_source->fullImageSize(); 0223 int imageWidth = fullImageSize.width(); 0224 int imageHeight = fullImageSize.height(); 0225 0226 mDebug() << QString( "TileCreator::createTiles() image dimensions %1 x %2").arg(imageWidth).arg(imageHeight); 0227 0228 if ( imageWidth < 1 || imageHeight < 1 ) { 0229 qDebug("Invalid imagemap!"); 0230 return; 0231 } 0232 0233 // Calculating Maximum Tile Level 0234 float approxMaxTileLevel = std::log( imageWidth / ( 2.0 * c_defaultTileSize ) ) / std::log( 2.0 ); 0235 0236 int maxTileLevel = 0; 0237 if ( approxMaxTileLevel == int( approxMaxTileLevel ) ) 0238 maxTileLevel = static_cast<int>( approxMaxTileLevel ); 0239 else 0240 maxTileLevel = static_cast<int>( approxMaxTileLevel + 1 ); 0241 0242 if ( maxTileLevel < 0 ) { 0243 mDebug() 0244 << QString( "TileCreator::createTiles(): Invalid Maximum Tile Level: %1" ) 0245 .arg( maxTileLevel ); 0246 } 0247 mDebug() << "Maximum Tile Level: " << maxTileLevel; 0248 0249 0250 if ( !QDir( d->m_targetDir ).exists() ) 0251 ( QDir::root() ).mkpath( d->m_targetDir ); 0252 0253 // Counting total amount of tiles to be generated for the progressbar 0254 // to prevent compiler warnings this var should 0255 // match the type of maxTileLevel 0256 int tileLevel = 0; 0257 int totalTileCount = 0; 0258 0259 while ( tileLevel <= maxTileLevel ) { 0260 totalTileCount += ( TileLoaderHelper::levelToRow( defaultLevelZeroRows, tileLevel ) 0261 * TileLoaderHelper::levelToColumn( defaultLevelZeroColumns, tileLevel ) ); 0262 tileLevel++; 0263 } 0264 0265 mDebug() << totalTileCount << " tiles to be created in total."; 0266 0267 int mmax = TileLoaderHelper::levelToColumn( defaultLevelZeroColumns, maxTileLevel ); 0268 int nmax = TileLoaderHelper::levelToRow( defaultLevelZeroRows, maxTileLevel ); 0269 0270 // Loading each row at highest spatial resolution and cropping tiles 0271 int percentCompleted = 0; 0272 int createdTilesCount = 0; 0273 QString tileName; 0274 0275 // Creating directory structure for the highest level 0276 QString dirName( d->m_targetDir 0277 + QString("%1").arg(maxTileLevel) ); 0278 if ( !QDir( dirName ).exists() ) 0279 ( QDir::root() ).mkpath( dirName ); 0280 0281 for ( int n = 0; n < nmax; ++n ) { 0282 QString dirName( d->m_targetDir 0283 + QString("%1/%2").arg(maxTileLevel).arg(n, tileDigits, 10, QLatin1Char('0'))); 0284 if ( !QDir( dirName ).exists() ) 0285 ( QDir::root() ).mkpath( dirName ); 0286 } 0287 0288 for ( int n = 0; n < nmax; ++n ) { 0289 0290 for ( int m = 0; m < mmax; ++m ) { 0291 0292 mDebug() << "** tile" << m << "x" << n; 0293 0294 if ( d->m_cancelled ) 0295 return; 0296 0297 tileName = d->m_targetDir + QString("%1/%2/%2_%3.%4") 0298 .arg( maxTileLevel ) 0299 .arg(n, tileDigits, 10, QLatin1Char('0')) 0300 .arg(m, tileDigits, 10, QLatin1Char('0')) 0301 .arg( d->m_tileFormat ); 0302 0303 if ( QFile::exists( tileName ) && d->m_resume ) { 0304 0305 //mDebug() << tileName << "exists already"; 0306 0307 } else { 0308 0309 QImage tile = d->m_source->tile( n, m, maxTileLevel ); 0310 0311 if ( tile.isNull() ) { 0312 mDebug() << "Read-Error! Null QImage!"; 0313 return; 0314 } 0315 0316 if (d->m_dem == QLatin1String("true")) { 0317 tile = tile.convertToFormat(QImage::Format_Indexed8, 0318 grayScalePalette, 0319 Qt::ThresholdDither); 0320 } 0321 0322 bool ok = tile.save(tileName, d->m_tileFormat.toLatin1().data(), d->m_tileFormat == QLatin1String("jpg") ? 100 : d->m_tileQuality); 0323 if ( !ok ) 0324 mDebug() << "Error while writing Tile: " << tileName; 0325 0326 mDebug() << tileName << "size" << QFile( tileName ).size(); 0327 0328 if ( d->m_verify ) { 0329 QImage writtenTile(tileName); 0330 Q_ASSERT( writtenTile.size() == tile.size() ); 0331 for ( int i=0; i < writtenTile.size().width(); ++i) { 0332 for ( int j=0; j < writtenTile.size().height(); ++j) { 0333 if ( writtenTile.pixel( i, j ) != tile.pixel( i, j ) ) { 0334 unsigned int pixel = tile.pixel( i, j); 0335 unsigned int writtenPixel = writtenTile.pixel( i, j); 0336 qWarning() << "***** pixel" << i << j << "is off by" << (pixel - writtenPixel) << "pixel" << pixel << "writtenPixel" << writtenPixel; 0337 QByteArray baPixel((char*)&pixel, sizeof(unsigned int)); 0338 qWarning() << "pixel" << baPixel.size() << "0x" << baPixel.toHex(); 0339 QByteArray baWrittenPixel((char*)&writtenPixel, sizeof(unsigned int)); 0340 qWarning() << "writtenPixel" << baWrittenPixel.size() << "0x" << baWrittenPixel.toHex(); 0341 Q_ASSERT(false); 0342 } 0343 } 0344 } 0345 } 0346 0347 } 0348 0349 percentCompleted = (int) ( 90 * (qreal)(createdTilesCount) 0350 / (qreal)(totalTileCount) ); 0351 createdTilesCount++; 0352 0353 mDebug() << "percentCompleted" << percentCompleted; 0354 emit progress( percentCompleted ); 0355 } 0356 } 0357 0358 mDebug() << "tileLevel: " << maxTileLevel << " successfully created."; 0359 0360 tileLevel = maxTileLevel; 0361 0362 // Now that we have the tiles at the highest resolution lets build 0363 // them together four by four. 0364 0365 while( tileLevel > 0 ) { 0366 tileLevel--; 0367 0368 int nmaxit = TileLoaderHelper::levelToRow( defaultLevelZeroRows, tileLevel ); 0369 0370 for ( int n = 0; n < nmaxit; ++n ) { 0371 QString dirName( d->m_targetDir 0372 + QString("%1/%2") 0373 .arg(tileLevel) 0374 .arg(n, tileDigits, 10, QLatin1Char('0'))); 0375 0376 // mDebug() << "dirName: " << dirName; 0377 if ( !QDir( dirName ).exists() ) 0378 ( QDir::root() ).mkpath( dirName ); 0379 0380 int mmaxit = TileLoaderHelper::levelToColumn( defaultLevelZeroColumns, tileLevel ); 0381 for ( int m = 0; m < mmaxit; ++m ) { 0382 0383 if ( d->m_cancelled ) 0384 return; 0385 0386 QString newTileName = d->m_targetDir + QString("%1/%2/%2_%3.%4") 0387 .arg( tileLevel ) 0388 .arg(n, tileDigits, 10, QLatin1Char('0')) 0389 .arg(m, tileDigits, 10, QLatin1Char('0')) 0390 .arg( d->m_tileFormat ); 0391 0392 if ( QFile::exists( newTileName ) && d->m_resume ) { 0393 //mDebug() << newTileName << "exists already"; 0394 } else { 0395 tileName = d->m_targetDir + QString("%1/%2/%2_%3.%4") 0396 .arg( tileLevel + 1 ) 0397 .arg(2*n, tileDigits, 10, QLatin1Char('0')) 0398 .arg(2*m, tileDigits, 10, QLatin1Char('0')) 0399 .arg( d->m_tileFormat ); 0400 QImage img_topleft( tileName ); 0401 0402 tileName = d->m_targetDir + QString("%1/%2/%2_%3.%4") 0403 .arg( tileLevel + 1 ) 0404 .arg(2*n, tileDigits, 10, QLatin1Char('0')) 0405 .arg(2*m+1, tileDigits, 10, QLatin1Char('0')) 0406 .arg( d->m_tileFormat ); 0407 QImage img_topright( tileName ); 0408 0409 tileName = d->m_targetDir + QString("%1/%2/%2_%3.%4") 0410 .arg( tileLevel + 1 ) 0411 .arg(2*n+1, tileDigits, 10, QLatin1Char('0')) 0412 .arg(2*m, tileDigits, 10, QLatin1Char('0')) 0413 .arg( d->m_tileFormat ); 0414 QImage img_bottomleft( tileName ); 0415 0416 tileName = d->m_targetDir + QString("%1/%2/%2_%3.%4") 0417 .arg( tileLevel + 1 ) 0418 .arg(2*n+1, tileDigits, 10, QLatin1Char('0')) 0419 .arg(2*m+1, tileDigits, 10, QLatin1Char('0')) 0420 .arg( d->m_tileFormat ); 0421 QImage img_bottomright( tileName ); 0422 0423 QSize const expectedSize( c_defaultTileSize, c_defaultTileSize ); 0424 if ( img_topleft.size() != expectedSize || 0425 img_topright.size() != expectedSize || 0426 img_bottomleft.size() != expectedSize || 0427 img_bottomright.size() != expectedSize ) { 0428 mDebug() << "Tile write failure. Missing write permissions?"; 0429 emit progress( 100 ); 0430 return; 0431 } 0432 QImage tile = img_topleft; 0433 0434 if (d->m_dem == QLatin1String("true")) { 0435 0436 tile.setColorTable( grayScalePalette ); 0437 uchar* destLine; 0438 0439 for ( uint y = 0; y < c_defaultTileSize / 2; ++y ) { 0440 destLine = tile.scanLine( y ); 0441 const uchar* srcLine = img_topleft.scanLine( 2 * y ); 0442 for ( uint x = 0; x < c_defaultTileSize / 2; ++x ) 0443 destLine[x] = srcLine[ 2*x ]; 0444 } 0445 for ( uint y = 0; y < c_defaultTileSize / 2; ++y ) { 0446 destLine = tile.scanLine( y ); 0447 const uchar* srcLine = img_topright.scanLine( 2 * y ); 0448 for ( uint x = c_defaultTileSize / 2; x < c_defaultTileSize; ++x ) 0449 destLine[x] = srcLine[ 2 * ( x - c_defaultTileSize / 2 ) ]; 0450 } 0451 for ( uint y = c_defaultTileSize / 2; y < c_defaultTileSize; ++y ) { 0452 destLine = tile.scanLine( y ); 0453 const uchar* srcLine = img_bottomleft.scanLine( 2 * ( y - c_defaultTileSize / 2 ) ); 0454 for ( uint x = 0; x < c_defaultTileSize / 2; ++x ) 0455 destLine[ x ] = srcLine[ 2 * x ]; 0456 } 0457 for ( uint y = c_defaultTileSize / 2; y < c_defaultTileSize; ++y ) { 0458 destLine = tile.scanLine( y ); 0459 const uchar* srcLine = img_bottomright.scanLine( 2 * ( y - c_defaultTileSize/2 ) ); 0460 for ( uint x = c_defaultTileSize / 2; x < c_defaultTileSize; ++x ) 0461 destLine[x] = srcLine[ 2 * ( x - c_defaultTileSize / 2 ) ]; 0462 } 0463 } 0464 else { 0465 0466 // tile.depth() != 8 0467 0468 img_topleft = img_topleft.convertToFormat( QImage::Format_ARGB32 ); 0469 img_topright = img_topright.convertToFormat( QImage::Format_ARGB32 ); 0470 img_bottomleft = img_bottomleft.convertToFormat( QImage::Format_ARGB32 ); 0471 img_bottomright = img_bottomright.convertToFormat( QImage::Format_ARGB32 ); 0472 tile = img_topleft; 0473 0474 QRgb* destLine; 0475 0476 for ( uint y = 0; y < c_defaultTileSize / 2; ++y ) { 0477 destLine = (QRgb*) tile.scanLine( y ); 0478 const QRgb* srcLine = (QRgb*) img_topleft.scanLine( 2 * y ); 0479 for ( uint x = 0; x < c_defaultTileSize / 2; ++x ) 0480 destLine[x] = srcLine[ 2 * x ]; 0481 } 0482 for ( uint y = 0; y < c_defaultTileSize / 2; ++y ) { 0483 destLine = (QRgb*) tile.scanLine( y ); 0484 const QRgb* srcLine = (QRgb*) img_topright.scanLine( 2 * y ); 0485 for ( uint x = c_defaultTileSize / 2; x < c_defaultTileSize; ++x ) 0486 destLine[x] = srcLine[ 2 * ( x - c_defaultTileSize / 2 ) ]; 0487 } 0488 for ( uint y = c_defaultTileSize / 2; y < c_defaultTileSize; ++y ) { 0489 destLine = (QRgb*) tile.scanLine( y ); 0490 const QRgb* srcLine = (QRgb*) img_bottomleft.scanLine( 2 * ( y-c_defaultTileSize/2 ) ); 0491 for ( uint x = 0; x < c_defaultTileSize / 2; ++x ) 0492 destLine[x] = srcLine[ 2 * x ]; 0493 } 0494 for ( uint y = c_defaultTileSize / 2; y < c_defaultTileSize; ++y ) { 0495 destLine = (QRgb*) tile.scanLine( y ); 0496 const QRgb* srcLine = (QRgb*) img_bottomright.scanLine( 2 * ( y-c_defaultTileSize / 2 ) ); 0497 for ( uint x = c_defaultTileSize / 2; x < c_defaultTileSize; ++x ) 0498 destLine[x] = srcLine[ 2*( x-c_defaultTileSize / 2 ) ]; 0499 } 0500 } 0501 0502 mDebug() << newTileName; 0503 0504 // Saving at 100% JPEG quality to have a high-quality 0505 // version to create the remaining needed tiles from. 0506 bool ok = tile.save(newTileName, d->m_tileFormat.toLatin1().data(), d->m_tileFormat == QLatin1String("jpg") ? 100 : d->m_tileQuality); 0507 if ( ! ok ) 0508 mDebug() << "Error while writing Tile: " << newTileName; 0509 } 0510 0511 percentCompleted = (int) ( 90 * (qreal)(createdTilesCount) 0512 / (qreal)(totalTileCount) ); 0513 createdTilesCount++; 0514 0515 emit progress( percentCompleted ); 0516 mDebug() << "percentCompleted" << percentCompleted; 0517 } 0518 } 0519 mDebug() << "tileLevel: " << tileLevel << " successfully created."; 0520 } 0521 mDebug() << "Tile creation completed."; 0522 0523 if (d->m_tileFormat == QLatin1String("jpg") && d->m_tileQuality != 100) { 0524 0525 // Applying correct lower JPEG compression now that we created all tiles 0526 int savedTilesCount = 0; 0527 0528 tileLevel = 0; 0529 while ( tileLevel <= maxTileLevel ) { 0530 int nmaxit = TileLoaderHelper::levelToRow( defaultLevelZeroRows, tileLevel ); 0531 for ( int n = 0; n < nmaxit; ++n) { 0532 int mmaxit = TileLoaderHelper::levelToColumn( defaultLevelZeroColumns, tileLevel ); 0533 for ( int m = 0; m < mmaxit; ++m) { 0534 0535 if ( d->m_cancelled ) 0536 return; 0537 0538 savedTilesCount++; 0539 0540 tileName = d->m_targetDir + QString("%1/%2/%2_%3.%4") 0541 .arg( tileLevel ) 0542 .arg(n, tileDigits, 10, QLatin1Char('0')) 0543 .arg(m, tileDigits, 10, QLatin1Char('0')) 0544 .arg( d->m_tileFormat ); 0545 QImage tile( tileName ); 0546 0547 bool ok; 0548 0549 ok = tile.save( tileName, d->m_tileFormat.toLatin1().data(), d->m_tileQuality ); 0550 0551 if ( !ok ) 0552 mDebug() << "Error while writing Tile: " << tileName; 0553 // Don't exceed 99% as this would cancel the thread unexpectedly 0554 percentCompleted = 90 + (int)( 9 * (qreal)(savedTilesCount) 0555 / (qreal)(totalTileCount) ); 0556 emit progress( percentCompleted ); 0557 mDebug() << "percentCompleted" << percentCompleted; 0558 //mDebug() << "Saving Tile #" << savedTilesCount 0559 // << " of " << totalTileCount 0560 // << " Percent: " << percentCompleted; 0561 } 0562 } 0563 tileLevel++; 0564 } 0565 } 0566 0567 percentCompleted = 100; 0568 emit progress( percentCompleted ); 0569 0570 mDebug() << "percentCompleted: " << percentCompleted; 0571 } 0572 0573 void TileCreator::setTileFormat(const QString& format) 0574 { 0575 d->m_tileFormat = format; 0576 } 0577 0578 QString TileCreator::tileFormat() const 0579 { 0580 return d->m_tileFormat; 0581 } 0582 0583 void TileCreator::setTileQuality(int quality) 0584 { 0585 d->m_tileQuality = quality; 0586 } 0587 0588 int TileCreator::tileQuality() const 0589 { 0590 return d->m_tileQuality; 0591 } 0592 0593 void TileCreator::setResume(bool resume) 0594 { 0595 d->m_resume = resume; 0596 } 0597 0598 bool TileCreator::resume() const 0599 { 0600 return d->m_resume; 0601 } 0602 0603 void TileCreator::setVerifyExactResult(bool verify) 0604 { 0605 d->m_verify = verify; 0606 } 0607 0608 bool TileCreator::verifyExactResult() const 0609 { 0610 return d->m_verify; 0611 } 0612 0613 0614 } 0615 0616 #include "moc_TileCreator.cpp"