Commit 8d288efed475d5037424ad8269c803159ebd5720
1 parent
2db5366c
matFormat almost complete
Showing
3 changed files
with
100 additions
and
12 deletions
sdk/core/qtutils.cpp
| ... | ... | @@ -113,7 +113,8 @@ void QtUtils::writeFile(const QString &file, const QByteArray &data, int compres |
| 113 | 113 | QFile f(file); |
| 114 | 114 | touchDir(f); |
| 115 | 115 | if (!f.open(QFile::WriteOnly)) qFatal("QtUtils::writeFile failed to open %s for writing.", qPrintable(file)); |
| 116 | - f.write(qCompress(data, compression)); | |
| 116 | + if (compression == 0) f.write(data); | |
| 117 | + else f.write(qCompress(data, compression)); | |
| 117 | 118 | f.close(); |
| 118 | 119 | } |
| 119 | 120 | ... | ... |
sdk/core/qtutils.h
sdk/plugins/format.cpp
| ... | ... | @@ -50,23 +50,20 @@ class csvFormat : public Format |
| 50 | 50 | QList< QList<float> > valsList; |
| 51 | 51 | foreach (const QString &line, lines) { |
| 52 | 52 | QList<float> vals; |
| 53 | - foreach (const QString &word, line.split(QRegExp(" *, *"))) { | |
| 53 | + foreach (const QString &word, line.split(QRegExp(" *, *"), QString::SkipEmptyParts)) { | |
| 54 | 54 | bool ok; |
| 55 | 55 | const float val = word.toFloat(&ok); |
| 56 | 56 | vals.append(val); |
| 57 | 57 | isUChar = isUChar && (val == float(uchar(val))); |
| 58 | 58 | } |
| 59 | - valsList.append(vals); | |
| 59 | + if (!vals.isEmpty()) | |
| 60 | + valsList.append(vals); | |
| 60 | 61 | } |
| 61 | 62 | |
| 62 | - assert((valsList.size() > 0) && (valsList[0].size() > 0)); | |
| 63 | 63 | Mat m(valsList.size(), valsList[0].size(), CV_32FC1); |
| 64 | - for (int i=0; i<valsList.size(); i++) { | |
| 65 | - assert(valsList[i].size() == valsList[0].size()); | |
| 66 | - for (int j=0; j<valsList[i].size(); j++) { | |
| 64 | + for (int i=0; i<valsList.size(); i++) | |
| 65 | + for (int j=0; j<valsList[i].size(); j++) | |
| 67 | 66 | m.at<float>(i,j) = valsList[i][j]; |
| 68 | - } | |
| 69 | - } | |
| 70 | 67 | |
| 71 | 68 | if (isUChar) m.convertTo(m, CV_8U); |
| 72 | 69 | return Template(m); |
| ... | ... | @@ -218,8 +215,8 @@ class matFormat : public Format |
| 218 | 215 | error |= (int(bytes) != stream.readRawData(data.data(), bytes)); |
| 219 | 216 | |
| 220 | 217 | // Alignment |
| 221 | - int skipBytes = (bytes < 4) ? (4 - bytes) : 0; | |
| 222 | - if (skipBytes != 0) error |= (skipBytes != stream.skipRawData(skipBytes)); | |
| 218 | + int skipBytes = (bytes < 4) ? (4 - bytes) : (8 - bytes%8)%8; | |
| 219 | + if (skipBytes != 0) stream.skipRawData(skipBytes); | |
| 223 | 220 | |
| 224 | 221 | if (error) qFatal("matFormat::Element Unexpected end of file."); |
| 225 | 222 | } |
| ... | ... | @@ -289,7 +286,98 @@ class matFormat : public Format |
| 289 | 286 | |
| 290 | 287 | void write(const Template &t) const |
| 291 | 288 | { |
| 289 | + QByteArray data; | |
| 290 | + QDataStream stream(&data, QFile::WriteOnly); | |
| 291 | + | |
| 292 | + { // Header | |
| 293 | + QByteArray header = "MATLAB 5.0 MAT-file; Made with OpenBR | www.openbiometrics.org\n"; | |
| 294 | + QByteArray buffer(116-header.size(), 0); | |
| 295 | + stream.writeRawData(header.data(), header.size()); | |
| 296 | + stream.writeRawData(buffer.data(), buffer.size()); | |
| 297 | + quint64 subsystem = 0; | |
| 298 | + quint16 version = 0x0100; | |
| 299 | + const char *endianness = "MI"; | |
| 300 | + stream.writeRawData((const char*)&subsystem, 8); | |
| 301 | + stream.writeRawData((const char*)&version, 2); | |
| 302 | + stream.writeRawData(endianness, 2); | |
| 303 | + } | |
| 304 | + | |
| 305 | + for (int i=0; i<t.size(); i++) { | |
| 306 | + const Mat &m = t[i]; | |
| 307 | + if (m.channels() != 1) qFatal("matFormat::write only supports single channel matrices."); | |
| 308 | + | |
| 309 | + QByteArray subdata; | |
| 310 | + QDataStream substream(&subdata, QFile::WriteOnly); | |
| 311 | + | |
| 312 | + { // Array Flags | |
| 313 | + quint32 type = 6; | |
| 314 | + quint32 bytes = 8; | |
| 315 | + quint64 arrayClass = 0; | |
| 316 | + switch (m.type()) { | |
| 317 | + case CV_64FC1: arrayClass = 6; break; | |
| 318 | + case CV_32FC1: arrayClass = 7; break; | |
| 319 | + case CV_8UC1: arrayClass = 8; break; | |
| 320 | + case CV_8SC1: arrayClass = 9; break; | |
| 321 | + case CV_16UC1: arrayClass = 10; break; | |
| 322 | + case CV_16SC1: arrayClass = 11; break; | |
| 323 | + case CV_32SC1: arrayClass = 12; break; | |
| 324 | + default: qFatal("matFormat::write unsupported matrix class."); | |
| 325 | + } | |
| 326 | + substream.writeRawData((const char*)&type, 4); | |
| 327 | + substream.writeRawData((const char*)&bytes, 4); | |
| 328 | + substream.writeRawData((const char*)&arrayClass, 8); | |
| 329 | + } | |
| 330 | + | |
| 331 | + { // Dimensions Array | |
| 332 | + quint32 type = 5; | |
| 333 | + quint32 bytes = 8; | |
| 334 | + substream.writeRawData((const char*)&type, 4); | |
| 335 | + substream.writeRawData((const char*)&bytes, 4); | |
| 336 | + substream.writeRawData((const char*)&m.rows, 4); | |
| 337 | + substream.writeRawData((const char*)&m.cols, 4); | |
| 338 | + } | |
| 339 | + | |
| 340 | + { // Array Name | |
| 341 | + QByteArray name(qPrintable(QString("OpenBR_%1").arg(QString::number(i)))); | |
| 342 | + quint32 type = 1; | |
| 343 | + quint32 bytes = name.size(); | |
| 344 | + QByteArray buffer((8 - bytes%8)%8, 0); | |
| 345 | + substream.writeRawData((const char*)&type, 4); | |
| 346 | + substream.writeRawData((const char*)&bytes, 4); | |
| 347 | + substream.writeRawData(name.data(), name.size()); | |
| 348 | + substream.writeRawData(buffer.data(), buffer.size()); | |
| 349 | + } | |
| 350 | + | |
| 351 | + { // Real part | |
| 352 | + quint32 type = 0; | |
| 353 | + switch (m.type()) { | |
| 354 | + case CV_8SC1: type = 1; break; | |
| 355 | + case CV_8UC1: type = 2; break; | |
| 356 | + case CV_16SC1: type = 3; break; | |
| 357 | + case CV_16UC1: type = 4; break; | |
| 358 | + case CV_32SC1: type = 5; break; | |
| 359 | + case CV_32FC1: type = 7; break; | |
| 360 | + case CV_64FC1: type = 9; break; | |
| 361 | + default: qFatal("matFormat::write unsupported matrix type."); | |
| 362 | + } | |
| 363 | + quint32 bytes = m.elemSize() * m.rows * m.cols; | |
| 364 | + QByteArray buffer((8 - bytes%8)%8, 0); | |
| 365 | + substream.writeRawData((const char*)&type, 4); | |
| 366 | + substream.writeRawData((const char*)&bytes, 4); | |
| 367 | + substream.writeRawData((const char*)m.data, bytes); | |
| 368 | + substream.writeRawData(buffer.data(), buffer.size()); | |
| 369 | + } | |
| 370 | + | |
| 371 | + { // Matrix | |
| 372 | + quint32 type = 14; | |
| 373 | + quint32 bytes = subdata.size(); | |
| 374 | + stream.writeRawData((const char*)&type, 4); | |
| 375 | + stream.writeRawData((const char*)&bytes, 4); | |
| 376 | + stream.writeRawData(subdata.data(), subdata.size()); | |
| 377 | + } | |
| 378 | + } | |
| 292 | 379 | |
| 380 | + QtUtils::writeFile(file, data); | |
| 293 | 381 | } |
| 294 | 382 | }; |
| 295 | 383 | ... | ... |