Add support for Matrix properties

This commit is contained in:
2023-01-30 18:27:22 +01:00
parent ed7e2c1a78
commit 024f770ee0
3 changed files with 105 additions and 7 deletions
+88 -3
View File
@@ -38,6 +38,43 @@ template<> struct std::hash<QString>
}
};
#endif
namespace LibXISF
{
class MatrixConvert
{
int _rows = 0;
int _cols = 0;
QByteArray _data;
public:
const QByteArray& data() const
{
return _data;
}
int rows() const { return _rows; }
int cols() const { return _cols; }
MatrixConvert() = default;
MatrixConvert(int rows, int cols, const QByteArray &data) : _rows(rows), _cols(cols), _data(data) {}
template<typename T>
static Matrix<T> toMatrix(const MatrixConvert &m)
{
Matrix<T> matrix(m._rows, m._cols);
std::memcpy(&matrix._elem[0], m._data.constData(), m._data.size());
return matrix;
}
template<typename T>
static MatrixConvert fromMatrix(const Matrix<T> &m)
{
MatrixConvert mc;
mc._rows = m._rows;
mc._cols = m._cols;
mc._data = QByteArray((const char*)&m._elem[0], mc._rows * mc._cols * sizeof(T));
return mc;
}
};
}
Q_DECLARE_METATYPE(LibXISF::MatrixConvert);
namespace LibXISF
{
@@ -51,6 +88,7 @@ static std::unordered_map<Image::SampleFormat, QString> sampleFormatToString;
static std::unordered_map<QString, Image::ColorSpace> colorSpaceToEnum;
static std::unordered_map<Image::ColorSpace, QString> colorSpaceToString;
static std::unordered_map<int, size_t> vectorTypeSizes;
static std::unordered_map<int, size_t> matrixTypeSizes;
static void byteShuffle(QByteArray &data, int itemSize)
{
@@ -594,6 +632,7 @@ Property XISFReader::readPropertyElement()
if(typeToId.count(type) == 0)
throw Error("Invalid type in property");
int typeId = typeToId[type];
QVariant value;
if(type == "String" && !attributes.hasAttribute("location"))
@@ -603,7 +642,7 @@ Property XISFReader::readPropertyElement()
else if(attributes.hasAttribute("value"))
{
value = attributes.value("value").toString();
value.convert(typeToId[type]);
value.convert(typeId);
property.value = value;
}
else
@@ -614,9 +653,28 @@ Property XISFReader::readPropertyElement()
_io->seek(dataBlock.attachmentPos);
dataBlock.decompress(_io->read(dataBlock.attachmentSize));
}
if(vectorTypeSizes.count(typeId))
{
property.value = dataBlock.data;
if(!property.value.convert(typeToId[type]))
throw Error("Failed to convert property data");
if(!property.value.convert(typeId))
throw Error("Failed to convert vector property data");
}
else if(matrixTypeSizes.count(typeId))
{
bool ok1, ok2;
int rows = attributes.value("rows").toInt(&ok1);
int cols = attributes.value("columns").toInt(&ok2);
if(!ok1 || !ok2)
throw Error("Invalid rows and/or columns");
property.value = QVariant::fromValue<MatrixConvert>(MatrixConvert(rows, cols, dataBlock.data));
if(!property.value.convert(typeId))
throw Error("Failed to convert matrix property data");
}
else
{
property.value = dataBlock.data;
}
}
return property;
@@ -886,6 +944,16 @@ void XISFWriter::writePropertyElement(const Property &property)
_xml->writeAttribute("length", QString::number(dataBlock.data.size() / vectorTypeSizes[type]));
_xml->writeCharacters(dataBlock.data.toBase64());
}
else if(matrixTypeSizes.count(type))
{
MatrixConvert mc = property.value.value<MatrixConvert>();
DataBlock dataBlock;
dataBlock.data = mc.data();
writeDataBlockAttributes(dataBlock);
_xml->writeAttribute("rows", QString::number(mc.rows()));
_xml->writeAttribute("columns", QString::number(mc.cols()));
_xml->writeCharacters(dataBlock.data.toBase64());
}
else
_xml->writeAttribute("value", property.value.toString());
_xml->writeEndElement();
@@ -925,6 +993,10 @@ void XISFWriter::writeMetadata()
return t; \
}); }
#define REGISTER_MATRIX_TYPE(type, mtype) { matrixTypeSizes.insert({typeToId[#type], sizeof(mtype)}); \
QMetaType::registerConverter<type, MatrixConvert>(MatrixConvert::fromMatrix<mtype>); \
QMetaType::registerConverter<MatrixConvert, type>(MatrixConvert::toMatrix<mtype>);}
struct Init
{
Init()
@@ -1010,6 +1082,19 @@ struct Init
REGISTER_VECTOR_TYPE(C32Vector);
REGISTER_VECTOR_TYPE(C64Vector);
REGISTER_MATRIX_TYPE(I8Matrix, Int8);
REGISTER_MATRIX_TYPE(UI8Matrix, UInt8);
REGISTER_MATRIX_TYPE(I16Matrix, Int16);
REGISTER_MATRIX_TYPE(UI16Matrix, UInt16);
REGISTER_MATRIX_TYPE(I32Matrix, Int32);
REGISTER_MATRIX_TYPE(UI32Matrix, UInt32);
REGISTER_MATRIX_TYPE(I64Matrix, Int64);
REGISTER_MATRIX_TYPE(UI64Matrix, UInt64);
REGISTER_MATRIX_TYPE(F32Matrix, Float32);
REGISTER_MATRIX_TYPE(F64Matrix, Float64);
REGISTER_MATRIX_TYPE(C32Matrix, Complex32);
REGISTER_MATRIX_TYPE(C64Matrix, Complex64);
QMetaType::registerConverter<Complex32, QString>([](const Complex32 &c){ return QString("(%1,%2)").arg(c.real).arg(c.imag); });
QMetaType::registerConverter<Complex64, QString>([](const Complex64 &c){ return QString("(%1,%2)").arg(c.real).arg(c.imag); });
QMetaType::registerConverter<QString, Complex32>([](QString s)
+10 -3
View File
@@ -251,9 +251,16 @@ struct Complex64
template<typename T>
class Matrix
{
int width;
int height;
std::vector<T> elem;
int _rows = 0;
int _cols = 0;
std::vector<T> _elem;
public:
Matrix() = default;
Matrix(int rows, int cols) : _rows(rows), _cols(cols), _elem(rows * cols) {}
void resize(int rows, int cols) { _rows = rows; _cols = cols; _elem.resize(rows * cols); }
T& operator()(int row, int col) { return _elem[row * _cols + col]; }
friend class MatrixConvert;
};
typedef bool Boolean;
+6
View File
@@ -48,6 +48,12 @@ int main(int argc, char **argv)
image.addProperty(Property("PropertyComplex64", Complex64{-3.0, 2.0}));
image.addProperty(Property("VectorUInt16", UI16Vector({23, 45, 86})));
image.addProperty(Property("VectorComplex32", C32Vector({{1, 2}, {3, 4}, {5, 6}})));
UI16Matrix m(2, 3);
m(0, 0) = 0;
m(0, 1) = 1;
m(0, 2) = 2;
m(1, 0) = 10;
image.addProperty(Property("UI16Matrix", m));
image.addFITSKeyword({"RA", "226.9751163116387", "Right ascension of the center of the image (deg)"});
image.addFITSKeyword({"DEC", "62.02302376908295", "Declination of the center of the image (deg)"});
writer.writeImage(image);