File indexing completed on 2024-12-22 04:17:16
0001 /*************************************************************************** 0002 * * 0003 * copyright : (C) 2005 C. Barth Netterfield * 0004 * netterfield@astro.utoronto.ca * 0005 * * 0006 * This program is free software; you can redistribute it and/or modify * 0007 * it under the terms of the GNU General Public License as published by * 0008 * the Free Software Foundation; either version 2 of the License, or * 0009 * (at your option) any later version. * 0010 * * 0011 ***************************************************************************/ 0012 0013 #include "qimagesource.h" 0014 0015 0016 #include <QXmlStreamWriter> 0017 #include <QImageReader> 0018 #include <QColor> 0019 0020 0021 using namespace Kst; 0022 0023 static const QString qimageTypeString = "QImage image"; 0024 0025 class QImageSource::Config { 0026 public: 0027 Config() { 0028 } 0029 0030 void read(QSettings *cfg, const QString& fileName = QString()) { 0031 Q_UNUSED(fileName); 0032 cfg->beginGroup(qimageTypeString); 0033 cfg->endGroup(); 0034 } 0035 0036 void save(QXmlStreamWriter& s) { 0037 Q_UNUSED(s); 0038 } 0039 0040 void load(const QDomElement& e) { 0041 Q_UNUSED(e); 0042 } 0043 }; 0044 0045 0046 0047 // 0048 // Vector interface 0049 // 0050 0051 class DataInterfaceQImageVector : public DataSource::DataInterface<DataVector> 0052 { 0053 public: 0054 DataInterfaceQImageVector(QImage* img) : _image(img), _frameCount(0) {} 0055 0056 // read one element 0057 int read(const QString&, DataVector::ReadInfo&); 0058 0059 // named elements 0060 QStringList list() const { return _vectorList; } 0061 bool isListComplete() const { return true; } 0062 bool isValid(const QString&) const; 0063 0064 // T specific 0065 const DataVector::DataInfo dataInfo(const QString&, int frame=0) const; 0066 void setDataInfo(const QString&, const DataVector::DataInfo&) {} 0067 0068 // meta data 0069 QMap<QString, double> metaScalars(const QString&); 0070 QMap<QString, QString> metaStrings(const QString&) { return QMap<QString, QString>(); } 0071 0072 0073 // no interface 0074 0075 QImage* _image; 0076 QStringList _vectorList; 0077 int _frameCount; 0078 0079 void init(); 0080 void clear(); 0081 }; 0082 0083 0084 void DataInterfaceQImageVector::clear() 0085 { 0086 _vectorList.clear(); 0087 _frameCount = 0; 0088 } 0089 0090 0091 void DataInterfaceQImageVector::init() 0092 { 0093 _vectorList.append( "GRAY" ); 0094 _vectorList.append( "RED" ); 0095 _vectorList.append( "GREEN" ); 0096 _vectorList.append( "BLUE" ); 0097 } 0098 0099 0100 const DataVector::DataInfo DataInterfaceQImageVector::dataInfo(const QString &field, int frame) const 0101 { 0102 Q_UNUSED(frame) 0103 if (!_vectorList.contains(field)) 0104 return DataVector::DataInfo(); 0105 0106 return DataVector::DataInfo(_frameCount, 1); 0107 } 0108 0109 0110 0111 int DataInterfaceQImageVector::read(const QString& field, DataVector::ReadInfo& p) 0112 { 0113 int i = 0; 0114 int s = p.startingFrame; 0115 int n = p.numberOfFrames; 0116 0117 if ( field=="INDEX" ) { 0118 for ( i=0; i<n; ++i ) { 0119 p.data[i] = i + s; 0120 } 0121 } else if ( field=="GRAY" ) { 0122 for ( i = s; i<s+n; ++i ) { 0123 int px = i%_image->width(); 0124 int py = i/_image->width(); 0125 p.data[i-s] = qGray( _image->pixel( px, py ) ); 0126 } 0127 } else if ( field=="RED" ) { 0128 for ( i=s; i<s+n; ++i ) { 0129 int px = i%_image->width(); 0130 int py = i/_image->width(); 0131 p.data[i-s] = qRed( _image->pixel( px, py ) ); 0132 } 0133 } else if ( field=="GREEN" ) { 0134 for ( i=s; i<s+n; ++i ) { 0135 int px = i%_image->width(); 0136 int py = i/_image->width(); 0137 p.data[i-s] = qGreen( _image->pixel( px, py ) ); 0138 } 0139 } else if ( field=="BLUE" ) { 0140 for ( i=s; i<s+n; ++i ) { 0141 int px = i%_image->width(); 0142 int py = i/_image->width(); 0143 p.data[i-s] = qBlue( _image->pixel( px, py ) ); 0144 } 0145 } 0146 0147 return i; 0148 } 0149 0150 0151 bool DataInterfaceQImageVector::isValid(const QString& field) const { 0152 return _vectorList.contains( field ); 0153 } 0154 0155 // TODO FRAMES only in vector? 0156 QMap<QString, double> DataInterfaceQImageVector::metaScalars(const QString&) 0157 { 0158 QMap<QString, double> m; 0159 m["FRAMES"] = _frameCount; 0160 return m; 0161 } 0162 0163 0164 // 0165 // Matrix interface 0166 // 0167 0168 class DataInterfaceQImageMatrix : public DataSource::DataInterface<DataMatrix> 0169 { 0170 public: 0171 0172 DataInterfaceQImageMatrix(QImage* img) : _image(img) {} 0173 0174 // read one element 0175 int read(const QString&, DataMatrix::ReadInfo&); 0176 0177 // named elements 0178 QStringList list() const { return _matrixList; } 0179 bool isListComplete() const { return true; } 0180 bool isValid(const QString&) const; 0181 0182 // T specific 0183 const DataMatrix::DataInfo dataInfo(const QString&, int frame=0) const; 0184 void setDataInfo(const QString&, const DataMatrix::DataInfo&) {} 0185 0186 // meta data 0187 QMap<QString, double> metaScalars(const QString&) { return QMap<QString, double>(); } 0188 QMap<QString, QString> metaStrings(const QString&) { return QMap<QString, QString>(); } 0189 0190 0191 // no interface 0192 QImage* _image; 0193 QStringList _matrixList; 0194 0195 void init(); 0196 void clear(); 0197 }; 0198 0199 void DataInterfaceQImageMatrix::clear() 0200 { 0201 _matrixList.clear(); 0202 } 0203 0204 void DataInterfaceQImageMatrix::init() 0205 { 0206 _matrixList.append( "GRAY" ); 0207 _matrixList.append( "RED" ); 0208 _matrixList.append( "GREEN" ); 0209 _matrixList.append( "BLUE" ); 0210 } 0211 0212 0213 0214 const DataMatrix::DataInfo DataInterfaceQImageMatrix::dataInfo(const QString& matrix, int frame) const 0215 { 0216 Q_UNUSED(frame) 0217 if ( !_image || _image->isNull() || !_matrixList.contains( matrix ) ) { 0218 return DataMatrix::DataInfo(); 0219 } 0220 0221 DataMatrix::DataInfo info; 0222 info.xSize = _image->width(); 0223 info.ySize = _image->height(); 0224 0225 return info; 0226 } 0227 0228 0229 int DataInterfaceQImageMatrix::read(const QString& field, DataMatrix::ReadInfo& p) 0230 { 0231 if ( _image->isNull() ) { 0232 return 0; 0233 } 0234 0235 int y0 = p.yStart; 0236 int y1 = p.yStart + p.yNumSteps; 0237 int x0 = p.xStart; 0238 int x1 = p.xStart + p.xNumSteps; 0239 double* z = p.data->z; 0240 0241 int i = 0; 0242 0243 if ( field=="GRAY") { 0244 for (int px = p.xStart; px<x1; ++px ) { 0245 for (int py=y1-1; py>=p.yStart; py-- ) { 0246 z[i] = qGray( _image->pixel( px, py ) ); 0247 ++i; 0248 } 0249 } 0250 } else if ( field=="RED" ) { 0251 for (int px = p.xStart; px<x1; ++px ) { 0252 for (int py=y1-1; py>=p.yStart; py-- ) { 0253 z[i] = qRed( _image->pixel( px, py ) ); 0254 ++i; 0255 } 0256 } 0257 } else if ( field=="GREEN" ) { 0258 for (int px = p.xStart; px<x1; ++px ) { 0259 for (int py=y1-1; py>=p.yStart; py-- ) { 0260 z[i] = qGreen( _image->pixel( px, py ) ); 0261 ++i; 0262 } 0263 } 0264 } else if ( field=="BLUE" ) { 0265 for (int px = p.xStart; px<x1; ++px ) { 0266 for (int py=y1-1; py>=p.yStart; py-- ) { 0267 z[i] = qBlue( _image->pixel( px, py ) ); 0268 ++i; 0269 } 0270 } 0271 } 0272 0273 // set the suggested matrix transform params: pixel index.... 0274 p.data->xMin = x0; 0275 p.data->yMin = y0; 0276 p.data->xStepSize = 1; 0277 p.data->yStepSize = 1; 0278 0279 return i; 0280 } 0281 0282 0283 bool DataInterfaceQImageMatrix::isValid(const QString& field) const { 0284 return _matrixList.contains( field ); 0285 } 0286 0287 0288 0289 0290 0291 // 0292 // QImageSource 0293 // 0294 0295 QImageSource::QImageSource(Kst::ObjectStore *store, QSettings *cfg, const QString& filename, const QString& type, const QDomElement& e) : 0296 Kst::DataSource(store, cfg, filename, type), 0297 _config(0L), 0298 iv(new DataInterfaceQImageVector(&_image)), 0299 im(new DataInterfaceQImageMatrix(&_image)) 0300 { 0301 setInterface(iv); 0302 setInterface(im); 0303 0304 startUpdating(None); 0305 0306 _valid = false; 0307 if (!type.isEmpty() && type != qimageTypeString) { 0308 return; 0309 } 0310 0311 _config = new QImageSource::Config; 0312 _config->read(cfg, filename); 0313 if (!e.isNull()) { 0314 _config->load(e); 0315 } 0316 0317 _image = QImage(); 0318 if (init()) { 0319 _valid = true; 0320 } 0321 registerChange(); 0322 } 0323 0324 0325 QImageSource::~QImageSource() { 0326 delete _config; 0327 _config = 0L; 0328 } 0329 0330 0331 const QString& QImageSource::typeString() const { 0332 return qimageTypeString; 0333 } 0334 0335 0336 void QImageSource::reset() { 0337 init(); 0338 Object::reset(); 0339 } 0340 0341 0342 bool QImageSource::init() 0343 { 0344 _image = QImage(); 0345 iv->clear(); 0346 im->clear(); 0347 if (!_image.load( _filename ) ) { 0348 return false; 0349 } 0350 iv->init(); 0351 im->init(); 0352 registerChange(); 0353 return true; 0354 } 0355 0356 0357 Kst::Object::UpdateType QImageSource::internalDataSourceUpdate() 0358 { 0359 int newNF = _image.width()*_image.height(); 0360 bool isnew = newNF != iv->_frameCount; 0361 0362 iv->_frameCount = newNF; 0363 0364 return (isnew ? Kst::Object::Updated : Kst::Object::NoChange); 0365 } 0366 0367 0368 bool QImageSource::isEmpty() const { 0369 return iv->_frameCount < 1; 0370 } 0371 0372 0373 QString QImageSource::fileType() const { 0374 return qimageTypeString; 0375 } 0376 0377 0378 void QImageSource::save(QXmlStreamWriter &streamWriter) { 0379 Kst::DataSource::save(streamWriter); 0380 } 0381 0382 /* TODO needed? 0383 int QImageSource::readScalar(double &S, const QString& scalar) { 0384 if (scalar == "FRAMES") { 0385 S = _frameCount; 0386 return 1; 0387 } 0388 return 0; 0389 } 0390 0391 0392 int QImageSource::readString(QString &S, const QString& string) { 0393 if (string == "FILE") { 0394 S = _filename; 0395 return 1; 0396 } 0397 return 0; 0398 } 0399 */ 0400 0401 0402 0403 0404 // 0405 // QImageSourcePlugin 0406 // 0407 0408 QString QImageSourcePlugin::pluginName() const { return tr("QImage Source Reader"); } 0409 QString QImageSourcePlugin::pluginDescription() const { return tr("QImage Source Reader"); } 0410 0411 0412 Kst::DataSource *QImageSourcePlugin::create(Kst::ObjectStore *store, 0413 QSettings *cfg, 0414 const QString &filename, 0415 const QString &type, 0416 const QDomElement &element) const { 0417 0418 return new QImageSource(store, cfg, filename, type, element); 0419 } 0420 0421 0422 0423 QStringList QImageSourcePlugin::matrixList(QSettings *cfg, 0424 const QString& filename, 0425 const QString& type, 0426 QString *typeSuggestion, 0427 bool *complete) const { 0428 0429 0430 if (typeSuggestion) { 0431 *typeSuggestion = qimageTypeString; 0432 } 0433 if ((!type.isEmpty() && !provides().contains(type)) || 0434 0 == understands(cfg, filename)) { 0435 if (complete) { 0436 *complete = false; 0437 } 0438 return QStringList(); 0439 } 0440 QStringList matrixList; 0441 0442 if (complete) { 0443 *complete = true; 0444 } 0445 0446 if ( !QImageReader::imageFormat( filename ).isEmpty() ) { 0447 matrixList.append( "GRAY" ); 0448 matrixList.append( "RED" ); 0449 matrixList.append( "GREEN" ); 0450 matrixList.append( "BLUE" ); 0451 } 0452 return matrixList; 0453 0454 } 0455 0456 0457 QStringList QImageSourcePlugin::scalarList(QSettings *cfg, 0458 const QString& filename, 0459 const QString& type, 0460 QString *typeSuggestion, 0461 bool *complete) const { 0462 0463 QStringList scalarList; 0464 0465 if ((!type.isEmpty() && !provides().contains(type)) || 0 == understands(cfg, filename)) { 0466 if (complete) { 0467 *complete = false; 0468 } 0469 return QStringList(); 0470 } 0471 0472 if (typeSuggestion) { 0473 *typeSuggestion = qimageTypeString; 0474 } 0475 0476 scalarList.append("FRAMES"); 0477 return scalarList; 0478 0479 } 0480 0481 0482 QStringList QImageSourcePlugin::stringList(QSettings *cfg, 0483 const QString& filename, 0484 const QString& type, 0485 QString *typeSuggestion, 0486 bool *complete) const { 0487 0488 QStringList stringList; 0489 0490 if ((!type.isEmpty() && !provides().contains(type)) || 0 == understands(cfg, filename)) { 0491 if (complete) { 0492 *complete = false; 0493 } 0494 return QStringList(); 0495 } 0496 0497 if (typeSuggestion) { 0498 *typeSuggestion = qimageTypeString; 0499 } 0500 0501 stringList.append("FILENAME"); 0502 return stringList; 0503 0504 } 0505 0506 QStringList QImageSourcePlugin::fieldList(QSettings *cfg, 0507 const QString& filename, 0508 const QString& type, 0509 QString *typeSuggestion, 0510 bool *complete) const { 0511 Q_UNUSED(type) 0512 Q_UNUSED(cfg) 0513 QStringList fieldList; 0514 0515 if (complete) { 0516 *complete = true; 0517 } 0518 0519 if (typeSuggestion) { 0520 *typeSuggestion = qimageTypeString; 0521 } 0522 if ( !QImageReader::imageFormat( filename ).isEmpty() ) { 0523 fieldList.append("INDEX"); 0524 fieldList.append( "GRAY" ); 0525 fieldList.append( "RED" ); 0526 fieldList.append( "GREEN" ); 0527 fieldList.append( "BLUE" ); 0528 } 0529 return fieldList; 0530 } 0531 0532 0533 int QImageSourcePlugin::understands(QSettings *cfg, const QString& filename) const { 0534 Q_UNUSED(cfg) 0535 0536 QList<QByteArray> formats = QImageReader::supportedImageFormats(); 0537 0538 bool matches = false; 0539 foreach (const QByteArray &ext, formats) { 0540 if (filename.toLower().endsWith(ext.toLower())) { 0541 matches = true; 0542 break; 0543 } 0544 } 0545 if (!matches) { 0546 return 0; 0547 } 0548 0549 QString ftype( QImageReader::imageFormat( filename ) ); 0550 0551 if ( ftype.isEmpty() ) 0552 return 0; 0553 0554 //QImageReader is incorrectly identifying some ascii files with 0555 // images. Enforce filenames (may not be needed anymore, since 0556 // we already know that the extension matches *some* image format. 0557 0558 //if ( ftype == "TIFF" ) { 0559 // if ( !filename.toLower().endsWith(".tif") ) return 0; 0560 //} 0561 //if ( ftype == "pcx" ) { 0562 // if ( !filename.toLower().endsWith(".pcx") ) return 0; 0563 //} 0564 0565 return 90; 0566 } 0567 0568 0569 0570 bool QImageSourcePlugin::supportsTime(QSettings *cfg, const QString& filename) const { 0571 //FIXME 0572 Q_UNUSED(cfg) 0573 Q_UNUSED(filename) 0574 return true; 0575 } 0576 0577 0578 QStringList QImageSourcePlugin::provides() const { 0579 QStringList rc; 0580 rc += qimageTypeString; 0581 return rc; 0582 } 0583 0584 0585 Kst::DataSourceConfigWidget *QImageSourcePlugin::configWidget(QSettings *cfg, const QString& filename) const { 0586 0587 Q_UNUSED(cfg) 0588 Q_UNUSED(filename) 0589 return 0;; 0590 0591 } 0592 0593 #ifndef QT5 0594 Q_EXPORT_PLUGIN2(kstdata_qimagesource, QImageSourcePlugin) 0595 #endif 0596 0597 // vim: ts=2 sw=2 et