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