File indexing completed on 2025-01-05 04:12:06
0001 /*************************************************************************** 0002 * * 0003 * copyright : (C) 2015 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 "tiff16source.h" 0014 #include <tiffio.h> 0015 0016 0017 #include <QXmlStreamWriter> 0018 #include <QColor> 0019 0020 0021 using namespace Kst; 0022 0023 static const QString tiff16TypeString = "Tiff16 image"; 0024 0025 class Tiff16Source::Config { 0026 public: 0027 Config() { 0028 } 0029 0030 void read(QSettings *cfg, const QString& fileName = QString()) { 0031 Q_UNUSED(fileName); 0032 cfg->beginGroup(tiff16TypeString); 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 DataInterfaceTiff16Vector : public DataSource::DataInterface<DataVector> 0052 { 0053 public: 0054 DataInterfaceTiff16Vector(unsigned short **z) : _z(z), _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 unsigned short **_z; 0076 0077 QStringList _vectorList; 0078 int _frameCount; 0079 0080 void init(); 0081 void clear(); 0082 }; 0083 0084 0085 void DataInterfaceTiff16Vector::clear() 0086 { 0087 _vectorList.clear(); 0088 _frameCount = 0; 0089 } 0090 0091 0092 void DataInterfaceTiff16Vector::init() 0093 { 0094 _vectorList.append( "GRAY" ); 0095 } 0096 0097 0098 const DataVector::DataInfo DataInterfaceTiff16Vector::dataInfo(const QString &field, int frame) const 0099 { 0100 Q_UNUSED(frame) 0101 if (!_vectorList.contains(field)) 0102 return DataVector::DataInfo(); 0103 0104 return DataVector::DataInfo(_frameCount, 1); 0105 } 0106 0107 0108 0109 int DataInterfaceTiff16Vector::read(const QString& field, DataVector::ReadInfo& p) 0110 { 0111 int i = 0; 0112 int s = p.startingFrame; 0113 int n = p.numberOfFrames; 0114 0115 if ( field=="INDEX" ) { 0116 for ( i=0; i<n; ++i ) { 0117 p.data[i] = i + s; 0118 } 0119 } else if ( field=="GRAY" ) { 0120 for ( i = s; i<s+n; ++i ) { 0121 p.data[i-s] = (*_z)[i]; 0122 } 0123 } 0124 0125 return i; 0126 } 0127 0128 0129 bool DataInterfaceTiff16Vector::isValid(const QString& field) const { 0130 return _vectorList.contains( field ); 0131 } 0132 0133 // TODO FRAMES only in vector? 0134 QMap<QString, double> DataInterfaceTiff16Vector::metaScalars(const QString&) 0135 { 0136 QMap<QString, double> m; 0137 m["FRAMES"] = _frameCount; 0138 return m; 0139 } 0140 0141 0142 // 0143 // Matrix interface 0144 // 0145 0146 class DataInterfaceTiff16Matrix : public DataSource::DataInterface<DataMatrix> 0147 { 0148 public: 0149 0150 DataInterfaceTiff16Matrix(unsigned short **z, int *width, int *height) : _image(z),_width(width),_height(height) {} 0151 0152 // read one element 0153 int read(const QString&, DataMatrix::ReadInfo&); 0154 0155 // named elements 0156 QStringList list() const { return _matrixList; } 0157 bool isListComplete() const { return true; } 0158 bool isValid(const QString&) const; 0159 0160 // T specific 0161 const DataMatrix::DataInfo dataInfo(const QString&, int frame=0) const; 0162 void setDataInfo(const QString&, const DataMatrix::DataInfo&) {} 0163 0164 // meta data 0165 QMap<QString, double> metaScalars(const QString&) { return QMap<QString, double>(); } 0166 QMap<QString, QString> metaStrings(const QString&) { return QMap<QString, QString>(); } 0167 0168 0169 // no interface 0170 unsigned short **_image; 0171 int *_width; 0172 int *_height; 0173 0174 QStringList _matrixList; 0175 0176 void init(); 0177 void clear(); 0178 }; 0179 0180 void DataInterfaceTiff16Matrix::clear() 0181 { 0182 _matrixList.clear(); 0183 } 0184 0185 void DataInterfaceTiff16Matrix::init() 0186 { 0187 _matrixList.append( "GRAY" ); 0188 } 0189 0190 0191 0192 const DataMatrix::DataInfo DataInterfaceTiff16Matrix::dataInfo(const QString& matrix, int frame) const 0193 { 0194 Q_UNUSED(frame) 0195 if ( !*_image || (*_width * *_height == 0) || !_matrixList.contains( matrix ) ) { 0196 return DataMatrix::DataInfo(); 0197 } 0198 0199 DataMatrix::DataInfo info; 0200 info.xSize = *_width; 0201 info.ySize = *_height; 0202 0203 return info; 0204 } 0205 0206 0207 int DataInterfaceTiff16Matrix::read(const QString& field, DataMatrix::ReadInfo& p) 0208 { 0209 if ( !*_image ) { 0210 return 0; 0211 } 0212 0213 int y0 = p.yStart; 0214 int y1 = p.yStart + p.yNumSteps; 0215 int x0 = p.xStart; 0216 int x1 = p.xStart + p.xNumSteps; 0217 double* z = p.data->z; 0218 0219 int i = 0, j; 0220 0221 if ( field=="GRAY") { 0222 for (int px = p.xStart; px<x1; ++px ) { 0223 for (int py=y1-1; py>=p.yStart; py-- ) { 0224 j = py * *_width + px; 0225 z[i] = (*_image)[j]; 0226 ++i; 0227 } 0228 } 0229 } 0230 // set the suggested matrix transform params: pixel index.... 0231 p.data->xMin = x0; 0232 p.data->yMin = y0; 0233 p.data->xStepSize = 1; 0234 p.data->yStepSize = 1; 0235 0236 return i; 0237 } 0238 0239 0240 bool DataInterfaceTiff16Matrix::isValid(const QString& field) const { 0241 return _matrixList.contains( field ); 0242 } 0243 0244 0245 0246 0247 0248 // 0249 // Tiff16Source 0250 // 0251 0252 Tiff16Source::Tiff16Source(Kst::ObjectStore *store, QSettings *cfg, const QString& filename, const QString& type, const QDomElement& e) : 0253 Kst::DataSource(store, cfg, filename, type), 0254 _z(NULL), _config(0L), 0255 iv(new DataInterfaceTiff16Vector(&_z)), 0256 im(new DataInterfaceTiff16Matrix(&_z, &_width, &_height)) 0257 { 0258 setInterface(iv); 0259 setInterface(im); 0260 0261 startUpdating(None); 0262 0263 _valid = false; 0264 if (!type.isEmpty() && type != tiff16TypeString) { 0265 return; 0266 } 0267 0268 _config = new Tiff16Source::Config; 0269 _config->read(cfg, filename); 0270 if (!e.isNull()) { 0271 _config->load(e); 0272 } 0273 0274 if (init()) { 0275 _valid = true; 0276 } 0277 registerChange(); 0278 } 0279 0280 0281 Tiff16Source::~Tiff16Source() { 0282 delete _config; 0283 delete [] _z; 0284 _z = 0L; 0285 _config = 0L; 0286 } 0287 0288 0289 const QString& Tiff16Source::typeString() const { 0290 return tiff16TypeString; 0291 } 0292 0293 0294 void Tiff16Source::reset() { 0295 init(); 0296 Object::reset(); 0297 } 0298 0299 0300 bool Tiff16Source::init() 0301 { 0302 //_image = Tiff16(); 0303 if (_z) { 0304 delete [] _z; 0305 _z = 0L; 0306 } 0307 0308 iv->clear(); 0309 im->clear(); 0310 0311 TIFF *tif=TIFFOpen(_filename.toAscii(), "r"); 0312 if (tif) { 0313 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &_width); 0314 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &_height); 0315 0316 _z = new unsigned short[_width*_height]; 0317 0318 char *buf = (char *)_z; 0319 0320 int linesize = TIFFScanlineSize(tif); 0321 for (int i = 0; i < _height; i++) { 0322 TIFFReadScanline(tif, &buf[i * linesize], i, 0); 0323 } 0324 } else { 0325 _width = _height = 0; 0326 } 0327 0328 iv->init(); 0329 im->init(); 0330 registerChange(); 0331 return true; 0332 } 0333 0334 0335 Kst::Object::UpdateType Tiff16Source::internalDataSourceUpdate() 0336 { 0337 int newNF = _width * _height; 0338 bool isnew = newNF != iv->_frameCount; 0339 0340 iv->_frameCount = newNF; 0341 0342 return (isnew ? Kst::Object::Updated : Kst::Object::NoChange); 0343 } 0344 0345 0346 bool Tiff16Source::isEmpty() const { 0347 return iv->_frameCount < 1; 0348 } 0349 0350 0351 QString Tiff16Source::fileType() const { 0352 return tiff16TypeString; 0353 } 0354 0355 0356 void Tiff16Source::save(QXmlStreamWriter &streamWriter) { 0357 Kst::DataSource::save(streamWriter); 0358 } 0359 0360 /* TODO needed? 0361 int Tiff16Source::readScalar(double &S, const QString& scalar) { 0362 if (scalar == "FRAMES") { 0363 S = _frameCount; 0364 return 1; 0365 } 0366 return 0; 0367 } 0368 0369 0370 int Tiff16Source::readString(QString &S, const QString& string) { 0371 if (string == "FILE") { 0372 S = _filename; 0373 return 1; 0374 } 0375 return 0; 0376 } 0377 */ 0378 0379 0380 0381 0382 // 0383 // Tiff16SourcePlugin 0384 // 0385 0386 QString Tiff16SourcePlugin::pluginName() const { return tr("Tiff16 Source Reader"); } 0387 QString Tiff16SourcePlugin::pluginDescription() const { return tr("Tiff16 Source Reader"); } 0388 0389 0390 Kst::DataSource *Tiff16SourcePlugin::create(Kst::ObjectStore *store, 0391 QSettings *cfg, 0392 const QString &filename, 0393 const QString &type, 0394 const QDomElement &element) const { 0395 0396 return new Tiff16Source(store, cfg, filename, type, element); 0397 } 0398 0399 0400 0401 QStringList Tiff16SourcePlugin::matrixList(QSettings *cfg, 0402 const QString& filename, 0403 const QString& type, 0404 QString *typeSuggestion, 0405 bool *complete) const { 0406 0407 0408 if (typeSuggestion) { 0409 *typeSuggestion = tiff16TypeString; 0410 } 0411 if ((!type.isEmpty() && !provides().contains(type)) || 0412 0 == understands(cfg, filename)) { 0413 if (complete) { 0414 *complete = false; 0415 } 0416 return QStringList(); 0417 } 0418 QStringList matrixList; 0419 0420 if (complete) { 0421 *complete = true; 0422 } 0423 0424 //if ( !Tiff16Reader::imageFormat( filename ).isEmpty() ) { 0425 matrixList.append( "GRAY" ); 0426 //} 0427 return matrixList; 0428 0429 } 0430 0431 0432 QStringList Tiff16SourcePlugin::scalarList(QSettings *cfg, 0433 const QString& filename, 0434 const QString& type, 0435 QString *typeSuggestion, 0436 bool *complete) const { 0437 0438 QStringList scalarList; 0439 0440 if ((!type.isEmpty() && !provides().contains(type)) || 0 == understands(cfg, filename)) { 0441 if (complete) { 0442 *complete = false; 0443 } 0444 return QStringList(); 0445 } 0446 0447 if (typeSuggestion) { 0448 *typeSuggestion = tiff16TypeString; 0449 } 0450 0451 scalarList.append("FRAMES"); 0452 return scalarList; 0453 0454 } 0455 0456 0457 QStringList Tiff16SourcePlugin::stringList(QSettings *cfg, 0458 const QString& filename, 0459 const QString& type, 0460 QString *typeSuggestion, 0461 bool *complete) const { 0462 0463 QStringList stringList; 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 = tiff16TypeString; 0474 } 0475 0476 stringList.append("FILENAME"); 0477 return stringList; 0478 0479 } 0480 0481 QStringList Tiff16SourcePlugin::fieldList(QSettings *cfg, 0482 const QString& filename, 0483 const QString& type, 0484 QString *typeSuggestion, 0485 bool *complete) const { 0486 Q_UNUSED(type) 0487 Q_UNUSED(cfg) 0488 QStringList fieldList; 0489 0490 if (complete) { 0491 *complete = true; 0492 } 0493 0494 if (typeSuggestion) { 0495 *typeSuggestion = tiff16TypeString; 0496 } 0497 0498 fieldList.append("INDEX"); 0499 fieldList.append( "GRAY" ); 0500 0501 return fieldList; 0502 } 0503 0504 0505 int Tiff16SourcePlugin::understands(QSettings *cfg, const QString& filename) const { 0506 Q_UNUSED(cfg) 0507 0508 quint16 spp, bpp, is_tiled; 0509 0510 if (filename.toLower().endsWith(".tiff") || 0511 filename.toLower().endsWith(".tif")) { 0512 0513 TIFF *tif=TIFFOpen(filename.toAscii(), "r"); 0514 0515 if (tif) { 0516 TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bpp); 0517 TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &spp); 0518 is_tiled = TIFFIsTiled(tif); 0519 0520 TIFFClose(tif); 0521 0522 0523 if ((bpp == 16) && (spp = 1) && (is_tiled == 0)) { 0524 return 91; 0525 } 0526 } 0527 } 0528 return 0; 0529 } 0530 0531 0532 0533 bool Tiff16SourcePlugin::supportsTime(QSettings *cfg, const QString& filename) const { 0534 //FIXME 0535 Q_UNUSED(cfg) 0536 Q_UNUSED(filename) 0537 return true; 0538 } 0539 0540 0541 QStringList Tiff16SourcePlugin::provides() const { 0542 QStringList rc; 0543 rc += tiff16TypeString; 0544 return rc; 0545 } 0546 0547 0548 Kst::DataSourceConfigWidget *Tiff16SourcePlugin::configWidget(QSettings *cfg, const QString& filename) const { 0549 0550 Q_UNUSED(cfg) 0551 Q_UNUSED(filename) 0552 return 0;; 0553 0554 } 0555 0556 #ifndef QT5 0557 Q_EXPORT_PLUGIN2(kstdata_tiff16source, Tiff16SourcePlugin) 0558 #endif 0559 0560 // vim: ts=2 sw=2 et