Hide member variable behind methods

This commit is contained in:
2023-01-29 17:27:57 +01:00
parent f8735a023d
commit 37c51d9a68
4 changed files with 326 additions and 116 deletions
+227 -54
View File
@@ -188,51 +188,189 @@ void normalToPlanar(void *_in, void *_out, size_t channels, size_t size)
out[o*size + i] = in[i*channels + o]; out[o*size + i] = in[i*channels + o];
} }
Image::Image(uint64_t width, uint64_t height, uint64_t channelCount, SampleFormat sampleFormat, ColorSpace colorSpace, PixelStorage pixelStorate) :
_pixelStorage(pixelStorate),
_sampleFormat(sampleFormat),
_colorSpace(colorSpace)
{
setGeometry(width, height, channelCount);
}
uint64_t Image::width() const
{
return _width;
}
uint64_t Image::height() const
{
return _height;
}
uint64_t Image::channelCount() const
{
return _channelCount;
}
void Image::setGeometry(uint64_t width, uint64_t height, uint64_t channelCount)
{
_width = width;
_height = height;
_channelCount = channelCount;
_dataBlock.data.resize(width * height * channelCount * sampleFormatSize(_sampleFormat));
}
const Bounds &Image::bounds() const
{
return _bounds;
}
void Image::setBounds(const Bounds &newBounds)
{
_bounds = newBounds;
}
Image::Type Image::imageType() const
{
return _imageType;
}
void Image::setImageType(Type newImageType)
{
_imageType = newImageType;
}
Image::PixelStorage Image::pixelStorage() const
{
return _pixelStorage;
}
void Image::setPixelStorage(PixelStorage newPixelStorage)
{
_pixelStorage = newPixelStorage;
}
Image::SampleFormat Image::sampleFormat() const
{
return _sampleFormat;
}
void Image::setSampleFormat(SampleFormat newSampleFormat)
{
_sampleFormat = newSampleFormat;
_dataBlock.data.resize(_width * _height * _channelCount * sampleFormatSize(_sampleFormat));
}
Image::ColorSpace Image::colorSpace() const
{
return _colorSpace;
}
void Image::setColorSpace(ColorSpace newColorSpace)
{
_colorSpace = newColorSpace;
}
const std::vector<Property>& Image::imageProperties() const
{
return _properties;
}
void Image::addProperty(const Property &property)
{
for(auto &p : _properties)
{
if(p.id == property.id)
throw Error("Duplicate property id");
}
_properties.push_back(property);
}
const std::vector<FITSKeyword> Image::fitsKeywords() const
{
return _fitsKeywords;
}
void Image::addFITSKeyword(const FITSKeyword &keyword)
{
_fitsKeywords.push_back(keyword);
}
void *Image::imageData()
{
return _dataBlock.data.data();
}
size_t Image::imageDataSize() const
{
return _dataBlock.data.size();
}
DataBlock::CompressionCodec Image::compression() const
{
return _dataBlock.codec;
}
void Image::setCompression(DataBlock::CompressionCodec compression, int level)
{
_dataBlock.codec = compression;
_dataBlock.compressLevel = level;
}
bool Image::byteShuffling() const
{
return _dataBlock.byteShuffling;
}
void Image::setByteshuffling(bool enable)
{
_dataBlock.byteShuffling = enable ? sampleFormatSize(_sampleFormat) : 0;
}
void Image::convertPixelStorageTo(PixelStorage storage) void Image::convertPixelStorageTo(PixelStorage storage)
{ {
if(pixelStorage == storage || channelCount <= 1) if(_pixelStorage == storage || _channelCount <= 1)
{ {
pixelStorage = storage; _pixelStorage = storage;
return; return;
} }
QByteArray tmp; QByteArray tmp;
tmp.resize(dataBlock.data.size()); tmp.resize(_dataBlock.data.size());
size_t size = width*height; size_t size = _width*_height;
switch(sampleFormat) switch(_sampleFormat)
{ {
case UInt8: case UInt8:
if(storage == Normal) if(storage == Normal)
planarToNormal<uint8_t>(dataBlock.data.data(), tmp.data(), channelCount, size); planarToNormal<uint8_t>(_dataBlock.data.data(), tmp.data(), _channelCount, size);
else else
normalToPlanar<uint8_t>(dataBlock.data.data(), tmp.data(), channelCount, size); normalToPlanar<uint8_t>(_dataBlock.data.data(), tmp.data(), _channelCount, size);
break; break;
case UInt16: case UInt16:
if(storage == Normal) if(storage == Normal)
planarToNormal<uint16_t>(dataBlock.data.data(), tmp.data(), channelCount, size); planarToNormal<uint16_t>(_dataBlock.data.data(), tmp.data(), _channelCount, size);
else else
normalToPlanar<uint16_t>(dataBlock.data.data(), tmp.data(), channelCount, size); normalToPlanar<uint16_t>(_dataBlock.data.data(), tmp.data(), _channelCount, size);
break; break;
case UInt32: case UInt32:
case Float32: case Float32:
if(storage == Normal) if(storage == Normal)
planarToNormal<uint32_t>(dataBlock.data.data(), tmp.data(), channelCount, size); planarToNormal<uint32_t>(_dataBlock.data.data(), tmp.data(), _channelCount, size);
else else
normalToPlanar<uint32_t>(dataBlock.data.data(), tmp.data(), channelCount, size); normalToPlanar<uint32_t>(_dataBlock.data.data(), tmp.data(), _channelCount, size);
break; break;
case UInt64: case UInt64:
case Float64: case Float64:
if(storage == Normal) if(storage == Normal)
planarToNormal<uint64_t>(dataBlock.data.data(), tmp.data(), channelCount, size); planarToNormal<uint64_t>(_dataBlock.data.data(), tmp.data(), _channelCount, size);
else else
normalToPlanar<uint64_t>(dataBlock.data.data(), tmp.data(), channelCount, size); normalToPlanar<uint64_t>(_dataBlock.data.data(), tmp.data(), _channelCount, size);
break; break;
default: default:
break; break;
} }
dataBlock.data = tmp; _dataBlock.data = tmp;
pixelStorage = storage; _pixelStorage = storage;
} }
Image::Type Image::imageTypeEnum(const QString &type) Image::Type Image::imageTypeEnum(const QString &type)
@@ -283,6 +421,22 @@ QString Image::colorSpaceString(ColorSpace colorSpace)
return t != colorSpaceToString.end() ? t->second : "Gray"; return t != colorSpaceToString.end() ? t->second : "Gray";
} }
size_t Image::sampleFormatSize(SampleFormat sampleFormat)
{
switch(sampleFormat)
{
case Image::UInt8: return sizeof(UInt8);
case Image::UInt16: return sizeof(UInt16);
case Image::UInt32: return sizeof(UInt32);
case Image::UInt64: return sizeof(UInt64);
case Image::Float32: return sizeof(Float32);
case Image::Float64: return sizeof(Float64);
case Image::Complex32: return sizeof(Complex32);
case Image::Complex64: return sizeof(Complex64);
}
return UInt16;
}
XISFReader::XISFReader() XISFReader::XISFReader()
{ {
_xml = std::make_unique<QXmlStreamReader>(); _xml = std::make_unique<QXmlStreamReader>();
@@ -331,10 +485,10 @@ const Image& XISFReader::getImage(uint32_t n)
throw Error("Out of bounds"); throw Error("Out of bounds");
Image &img = _images[n]; Image &img = _images[n];
if(img.dataBlock.attachmentPos) if(img._dataBlock.attachmentPos)
{ {
_io->seek(img.dataBlock.attachmentPos); _io->seek(img._dataBlock.attachmentPos);
img.dataBlock.decompress(_io->read(img.dataBlock.attachmentSize)); img._dataBlock.decompress(_io->read(img._dataBlock.attachmentSize));
} }
return img; return img;
} }
@@ -386,40 +540,42 @@ void XISFReader::readImageElement()
QVector<QStringRef> geometry = attributes.value("geometry").split(":"); QVector<QStringRef> geometry = attributes.value("geometry").split(":");
if(geometry.size() != 3)throw Error("We support only 2D images"); if(geometry.size() != 3)throw Error("We support only 2D images");
image.width = geometry[0].toULongLong(); image._width = geometry[0].toULongLong();
image.height = geometry[1].toULongLong(); image._height = geometry[1].toULongLong();
image.channelCount = geometry[2].toULongLong(); image._channelCount = geometry[2].toULongLong();
if(!image.width || !image.height || !image.channelCount)throw Error("Invalid image geometry"); if(!image._width || !image._height || !image._channelCount)throw Error("Invalid image geometry");
QVector<QStringRef> bounds = attributes.value("bounds").split(":"); QVector<QStringRef> bounds = attributes.value("bounds").split(":");
if(bounds.size() == 2) if(bounds.size() == 2)
{ {
image.bounds[0] = bounds[0].toDouble(); image._bounds.first = bounds[0].toDouble();
image.bounds[1] = bounds[1].toDouble(); image._bounds.second = bounds[1].toDouble();
} }
image.imageType = Image::imageTypeEnum(attributes.value("imageType").toString()); image._imageType = Image::imageTypeEnum(attributes.value("imageType").toString());
image.pixelStorage = Image::pixelStorageEnum(attributes.value("pixelStorage").toString()); image._pixelStorage = Image::pixelStorageEnum(attributes.value("pixelStorage").toString());
image.sampleFormat = Image::sampleFormatEnum(attributes.value("sampleFormat").toString()); image._sampleFormat = Image::sampleFormatEnum(attributes.value("sampleFormat").toString());
image.colorSpace = Image::colorSpaceEnum(attributes.value("colorSpace").toString()); image._colorSpace = Image::colorSpaceEnum(attributes.value("colorSpace").toString());
image.dataBlock = readDataBlock(); image._dataBlock = readDataBlock();
while(_xml->readNext() != QXmlStreamReader::EndElement || _xml->name() != "Image") while(_xml->readNext() != QXmlStreamReader::EndElement || _xml->name() != "Image")
{ {
if(_xml->tokenType() == QXmlStreamReader::StartElement) if(_xml->tokenType() == QXmlStreamReader::StartElement)
{ {
if(_xml->name() == "Property") if(_xml->name() == "Property")
image.properties.push_back(readPropertyElement()); image._properties.push_back(readPropertyElement());
else if(_xml->name() == "FITSKeyword") else if(_xml->name() == "FITSKeyword")
image.fitsKeywords.push_back(readFITSKeyword()); image._fitsKeywords.push_back(readFITSKeyword());
else if(_xml->name() == "ICCProfile") else if(_xml->name() == "ICCProfile")
{ {
DataBlock icc = readDataBlock(); DataBlock icc = readDataBlock();
image.iccProfile = icc.data; image._iccProfile = icc.data;
} }
else else
_xml->skipCurrentElement(); _xml->skipCurrentElement();
} }
if(_xml->hasError())
throw Error("Error while reading XISF header");
} }
_images.push_back(std::move(image)); _images.push_back(std::move(image));
@@ -430,16 +586,36 @@ Property XISFReader::readPropertyElement()
QXmlStreamAttributes attributes = _xml->attributes(); QXmlStreamAttributes attributes = _xml->attributes();
Property property; Property property;
property.id = attributes.value("id").toString(); property.id = attributes.value("id").toString();
property.format = attributes.value("format").toString();
property.comment = attributes.value("comment").toString(); property.comment = attributes.value("comment").toString();
QString type = attributes.value("type").toString(); QString type = attributes.value("type").toString();
if(typeToId.count(type) == 0) if(typeToId.count(type) == 0)
throw Error("Invalid type in property"); throw Error("Invalid type in property");
QVariant value = attributes.value("value").toString(); QVariant value;
value.convert(typeToId[type]);
property.value = value; if(type == "String")
{
property.value = _xml->readElementText();
}
else if(attributes.hasAttribute("value"))
{
value = attributes.value("value").toString();
value.convert(typeToId[type]);
property.value = value;
}
else
{
//TODO properly handle data block properties
throw Error("Data block properties not supported");
/*DataBlock dataBlock = readDataBlock();
if(dataBlock.attachmentPos)
{
_io->seek(dataBlock.attachmentPos);
dataBlock.decompress(_io->read(dataBlock.attachmentSize));
}
property.value = dataBlock.data;*/
}
return property; return property;
} }
@@ -531,7 +707,7 @@ void XISFReader::readCompression(DataBlock &dataBlock)
XISFWriter::XISFWriter() XISFWriter::XISFWriter()
{ {
_xml = std::make_unique<QXmlStreamWriter>(); _xml = std::make_unique<QXmlStreamWriter>();
_xml->setAutoFormatting(true); //_xml->setAutoFormatting(true);
} }
void XISFWriter::save(const QString &name) void XISFWriter::save(const QString &name)
@@ -559,15 +735,15 @@ void XISFWriter::save(QIODevice &io)
for(auto &image : _images) for(auto &image : _images)
{ {
io.write(image.dataBlock.data); io.write(image._dataBlock.data);
} }
} }
void XISFWriter::writeImage(const Image &image) void XISFWriter::writeImage(const Image &image)
{ {
_images.push_back(image); _images.push_back(image);
_images.back().dataBlock.attachmentPos = 1; _images.back()._dataBlock.attachmentPos = 1;
_images.back().dataBlock.compress(); _images.back()._dataBlock.compress();
} }
void XISFWriter::writeHeader() void XISFWriter::writeHeader()
@@ -605,7 +781,7 @@ void XISFWriter::writeHeader()
{ {
QByteArray blockPos = QByteArray("attachment:") + QByteArray::number(size + offset); QByteArray blockPos = QByteArray("attachment:") + QByteArray::number(size + offset);
_xisfHeader.replace(_xisfHeader.indexOf(replace), sizeof(replace) - 1, blockPos); _xisfHeader.replace(_xisfHeader.indexOf(replace), sizeof(replace) - 1, blockPos);
offset += image.dataBlock.data.size(); offset += image._dataBlock.data.size();
} }
uint32_t headerSize = _xisfHeader.size() - sizeof(signature); uint32_t headerSize = _xisfHeader.size() - sizeof(signature);
@@ -621,21 +797,21 @@ void XISFWriter::writeHeader()
void XISFWriter::writeImageElement(const Image &image) void XISFWriter::writeImageElement(const Image &image)
{ {
_xml->writeStartElement("Image"); _xml->writeStartElement("Image");
_xml->writeAttribute("geometry", QString("%1:%2:%3").arg(image.width).arg(image.height).arg(image.channelCount)); _xml->writeAttribute("geometry", QString("%1:%2:%3").arg(image._width).arg(image._height).arg(image._channelCount));
_xml->writeAttribute("sampleFormat", Image::sampleFormatString(image.sampleFormat)); _xml->writeAttribute("sampleFormat", Image::sampleFormatString(image._sampleFormat));
_xml->writeAttribute("colorSpace", Image::colorSpaceString(image.colorSpace)); _xml->writeAttribute("colorSpace", Image::colorSpaceString(image._colorSpace));
_xml->writeAttribute("imageType", Image::imageTypeString(image.imageType)); _xml->writeAttribute("imageType", Image::imageTypeString(image._imageType));
if((image.sampleFormat == Image::Float32 || image.sampleFormat == Image::Float64) || if((image._sampleFormat == Image::Float32 || image._sampleFormat == Image::Float64) ||
image.bounds[0] != 0.0 || image.bounds[1] != 1.0) image._bounds.first != 0.0 || image._bounds.second != 1.0)
{ {
_xml->writeAttribute("bounds", QString("%1:%2").arg(image.bounds[0])); _xml->writeAttribute("bounds", QString("%1:%2").arg(image._bounds.first).arg(image._bounds.second));
} }
writeDataBlockAttributes(image.dataBlock); writeDataBlockAttributes(image._dataBlock);
for(auto &property : image.properties) for(auto &property : image._properties)
writePropertyElement(property); writePropertyElement(property);
for(auto &fitsKeyword : image.fitsKeywords) for(auto &fitsKeyword : image._fitsKeywords)
writeFITSKeyword(fitsKeyword); writeFITSKeyword(fitsKeyword);
_xml->writeEndElement(); _xml->writeEndElement();
@@ -691,9 +867,6 @@ void XISFWriter::writePropertyElement(const Property &property)
_xml->writeAttribute("id", property.id); _xml->writeAttribute("id", property.id);
_xml->writeAttribute("type", idToType[type]); _xml->writeAttribute("type", idToType[type]);
if(!property.format.isEmpty())
_xml->writeAttribute("format", property.format);
if(!property.comment.isEmpty()) if(!property.comment.isEmpty())
_xml->writeAttribute("comment", property.comment); _xml->writeAttribute("comment", property.comment);
+60 -16
View File
@@ -45,17 +45,17 @@ struct DataBlock
uint64_t attachmentSize = 0; uint64_t attachmentSize = 0;
uint64_t uncompressedSize = 0; uint64_t uncompressedSize = 0;
CompressionCodec codec = None; CompressionCodec codec = None;
int compressLevel = -1;
QByteArray data; QByteArray data;
void decompress(const QByteArray &input, const QString &encoding = ""); void decompress(const QByteArray &input, const QString &encoding = "");
void compress(); void compress();
}; };
struct Property struct LIBXISF_EXPORT Property
{ {
QString id; QString id;
QVariant value; QVariant value;
QString comment; QString comment;
QString format;
Property() = default; Property() = default;
Property(const Property &) = default; Property(const Property &) = default;
@@ -66,15 +66,18 @@ struct Property
value(QVariant::fromValue<T>(_value)){} value(QVariant::fromValue<T>(_value)){}
}; };
struct FITSKeyword struct LIBXISF_EXPORT FITSKeyword
{ {
QString name; QString name;
QString value; QString value;
QString comment; QString comment;
}; };
struct Image typedef std::pair<double, double> Bounds;
class LIBXISF_EXPORT Image
{ {
public:
enum Type enum Type
{ {
Bias, Bias,
@@ -92,6 +95,9 @@ struct Image
SlopeMap, SlopeMap,
WeightMap WeightMap
}; };
/**
Planar - each channel samples are stored separately for example RGB image will be stored RRRRGGGGBBBB
Normal - channel values for each pixel are stored inteleaved RGBRGBRGBRGB */
enum PixelStorage enum PixelStorage
{ {
Planar, Planar,
@@ -114,20 +120,38 @@ struct Image
RGB, RGB,
CIELab CIELab
}; };
Image() = default;
Image(uint64_t width, uint64_t height, uint64_t channelCount = 1, SampleFormat sampleFormat = UInt16, ColorSpace colorSpace = Gray, PixelStorage pixelStorate = Planar);
uint64_t width = 0; uint64_t width() const;
uint64_t height = 0; uint64_t height() const;
uint64_t channelCount = 1; uint64_t channelCount() const;
double bounds[2] = {0.0, 1.0}; void setGeometry(uint64_t width, uint64_t height, uint64_t channelCount);
Type imageType = Light; const Bounds &bounds() const;
PixelStorage pixelStorage = Planar; void setBounds(const Bounds &newBounds);
SampleFormat sampleFormat = UInt16; Type imageType() const;
ColorSpace colorSpace = Gray; void setImageType(Type newImageType);
DataBlock dataBlock; PixelStorage pixelStorage() const;
QByteArray iccProfile; void setPixelStorage(PixelStorage newPixelStorage);
std::vector<Property> properties; SampleFormat sampleFormat() const;
std::vector<FITSKeyword> fitsKeywords; void setSampleFormat(SampleFormat newSampleFormat);
ColorSpace colorSpace() const;
void setColorSpace(ColorSpace newColorSpace);
const std::vector<Property> &imageProperties() const;
void addProperty(const Property &property);
const std::vector<FITSKeyword> fitsKeywords() const;
void addFITSKeyword(const FITSKeyword &keyword);
void* imageData();
template<typename T>
T* imageData(){ return static_cast<T*>(imageData()); }
size_t imageDataSize() const;
DataBlock::CompressionCodec compression() const;
void setCompression(DataBlock::CompressionCodec compression, int level = -1);
bool byteShuffling() const;
void setByteshuffling(bool enable);
/** Convert between Planar and Normal storage format s*/
void convertPixelStorageTo(PixelStorage storage); void convertPixelStorageTo(PixelStorage storage);
static Type imageTypeEnum(const QString &type); static Type imageTypeEnum(const QString &type);
@@ -138,6 +162,24 @@ struct Image
static QString sampleFormatString(SampleFormat format); static QString sampleFormatString(SampleFormat format);
static ColorSpace colorSpaceEnum(const QString &colorSpace); static ColorSpace colorSpaceEnum(const QString &colorSpace);
static QString colorSpaceString(ColorSpace colorSpace); static QString colorSpaceString(ColorSpace colorSpace);
static size_t sampleFormatSize(SampleFormat sampleFormat);
private:
uint64_t _width = 0;
uint64_t _height = 0;
uint64_t _channelCount = 1;
Bounds _bounds = {0.0, 1.0};
Type _imageType = Light;
PixelStorage _pixelStorage = Planar;
SampleFormat _sampleFormat = UInt16;
ColorSpace _colorSpace = Gray;
DataBlock _dataBlock;
QByteArray _iccProfile;
std::vector<Property> _properties;
std::vector<FITSKeyword> _fitsKeywords;
friend class XISFReader;
friend class XISFWriter;
}; };
class LIBXISF_EXPORT XISFReader class LIBXISF_EXPORT XISFReader
@@ -148,7 +190,9 @@ public:
void open(const QByteArray &data); void open(const QByteArray &data);
/** Open image from QIODevice. This method takes ownership of *io pointer */ /** Open image from QIODevice. This method takes ownership of *io pointer */
void open(QIODevice *io); void open(QIODevice *io);
/** Close opended file release all data. */
void close(); void close();
/** Return number of images inside file */
int imagesCount() const; int imagesCount() const;
const Image& getImage(uint32_t n); const Image& getImage(uint32_t n);
private: private:
+9 -14
View File
@@ -11,21 +11,16 @@ void benchmarkType(float avg, float stdDev)
std::mt19937 gen; std::mt19937 gen;
std::normal_distribution<float> normalDist {avg, stdDev}; std::normal_distribution<float> normalDist {avg, stdDev};
Image image(2048, 2048);
UInt32 pixels = 2048*2048; UInt32 pixels = 2048*2048;
UInt32 size = pixels*sizeof(T); UInt32 size = pixels*sizeof(T);
QByteArray imageData; T *ptr = (T*)image.imageData();
imageData.resize(size);
T *ptr = (T*)imageData.data();
for(UInt32 i=0; i < pixels; i++) for(UInt32 i=0; i < pixels; i++)
{ {
ptr[i] = normalDist(gen); ptr[i] = normalDist(gen);
} }
QElapsedTimer timer; QElapsedTimer timer;
Image image;
image.width = 2048;
image.height = 2048;
image.dataBlock.data = imageData;
double baseSize; double baseSize;
{ {
@@ -39,7 +34,7 @@ void benchmarkType(float avg, float stdDev)
<< size/1024.0/1.024/timer.elapsed() << "MiB/s" << std::endl; << size/1024.0/1.024/timer.elapsed() << "MiB/s" << std::endl;
} }
{ {
image.dataBlock.codec = DataBlock::Zlib; image.setCompression(DataBlock::Zlib);
timer.start(); timer.start();
XISFWriter writer; XISFWriter writer;
writer.writeImage(image); writer.writeImage(image);
@@ -49,7 +44,7 @@ void benchmarkType(float avg, float stdDev)
<< size/1024.0/1.024/timer.elapsed() << "MiB/s\tRatio: " << baseSize/xisfImage.size() << std::endl; << size/1024.0/1.024/timer.elapsed() << "MiB/s\tRatio: " << baseSize/xisfImage.size() << std::endl;
} }
{ {
image.dataBlock.codec = DataBlock::LZ4; image.setCompression(DataBlock::LZ4);
timer.start(); timer.start();
XISFWriter writer; XISFWriter writer;
writer.writeImage(image); writer.writeImage(image);
@@ -59,7 +54,7 @@ void benchmarkType(float avg, float stdDev)
<< size/1024.0/1.024/timer.elapsed() << "MiB/s\tRatio: " << baseSize/xisfImage.size() << std::endl; << size/1024.0/1.024/timer.elapsed() << "MiB/s\tRatio: " << baseSize/xisfImage.size() << std::endl;
} }
{ {
image.dataBlock.codec = DataBlock::LZ4HC; image.setCompression(DataBlock::LZ4HC);
timer.start(); timer.start();
XISFWriter writer; XISFWriter writer;
writer.writeImage(image); writer.writeImage(image);
@@ -68,9 +63,9 @@ void benchmarkType(float avg, float stdDev)
std::cout << "LZ4HC compression \tElapsed time: " << timer.elapsed() << " " << "ms\tSpeed: " std::cout << "LZ4HC compression \tElapsed time: " << timer.elapsed() << " " << "ms\tSpeed: "
<< size/1024.0/1.024/timer.elapsed() << "MiB/s\tRatio: " << baseSize/xisfImage.size() << std::endl; << size/1024.0/1.024/timer.elapsed() << "MiB/s\tRatio: " << baseSize/xisfImage.size() << std::endl;
} }
image.dataBlock.byteShuffling = sizeof(T); image.setByteshuffling(true);
{ {
image.dataBlock.codec = DataBlock::Zlib; image.setCompression(DataBlock::Zlib);
timer.start(); timer.start();
XISFWriter writer; XISFWriter writer;
writer.writeImage(image); writer.writeImage(image);
@@ -80,7 +75,7 @@ void benchmarkType(float avg, float stdDev)
<< size/1024.0/1.024/timer.elapsed() << "MiB/s\tRatio: " << baseSize/xisfImage.size() << std::endl; << size/1024.0/1.024/timer.elapsed() << "MiB/s\tRatio: " << baseSize/xisfImage.size() << std::endl;
} }
{ {
image.dataBlock.codec = DataBlock::LZ4; image.setCompression(DataBlock::LZ4);
timer.start(); timer.start();
XISFWriter writer; XISFWriter writer;
writer.writeImage(image); writer.writeImage(image);
@@ -90,7 +85,7 @@ void benchmarkType(float avg, float stdDev)
<< size/1024.0/1.024/timer.elapsed() << "MiB/s\tRatio: " << baseSize/xisfImage.size() << std::endl; << size/1024.0/1.024/timer.elapsed() << "MiB/s\tRatio: " << baseSize/xisfImage.size() << std::endl;
} }
{ {
image.dataBlock.codec = DataBlock::LZ4HC; image.setCompression(DataBlock::LZ4HC);
timer.start(); timer.start();
XISFWriter writer; XISFWriter writer;
writer.writeImage(image); writer.writeImage(image);
+30 -32
View File
@@ -32,30 +32,27 @@ int main(int argc, char **argv)
if (argc < 2) if (argc < 2)
{ {
XISFWriter writer; XISFWriter writer;
Image image; Image image(5, 7);
image.width = 5; image.setImageType(Image::Light);
image.height = 7; image.addProperty(Property("PropertyString", "Hello XISF"));
image.imageType = Image::Light; image.addProperty(Property("PropertyBoolean", (Boolean)true));
image.dataBlock.data.resize(image.width*image.height*2); image.addProperty(Property("PropertyInt8", (Int8)(8)));
image.properties.push_back(Property("PropertyString", "Hello XISF")); image.addProperty(Property("PropertyInt16", (Int16)16));
image.properties.push_back(Property("PropertyBoolean", (Boolean)true)); image.addProperty(Property("PropertyInt32", 32));
image.properties.push_back(Property("PropertyInt8", (Int8)(8))); image.addProperty(Property("PropertyUInt8", (UInt8)8));
image.properties.push_back(Property("PropertyInt16", (Int16)16)); image.addProperty(Property("PropertyUInt16", (UInt16)(16)));
image.properties.push_back(Property("PropertyInt32", 32)); image.addProperty(Property("PropertyUInt32", (uint32_t)32));
image.properties.push_back(Property("PropertyUInt8", (UInt8)8)); image.addProperty(Property("PropertyFloat32", (Float32) 0.32));
image.properties.push_back(Property("PropertyUInt16", (UInt16)(16))); image.addProperty(Property("PropertyFloat64", (Float64) 0.64));
image.properties.push_back(Property("PropertyUInt32", (uint32_t)32)); image.addProperty(Property("PropertyComplex32", Complex32{3.0, -2.0}));
image.properties.push_back(Property("PropertyFloat32", (Float32) 0.32)); image.addProperty(Property("PropertyComplex64", Complex64{-3.0, 2.0}));
image.properties.push_back(Property("PropertyFloat64", (Float64) 0.64)); image.addFITSKeyword({"RA", "226.9751163116387", "Right ascension of the center of the image (deg)"});
image.properties.push_back(Property("PropertyComplex32", Complex32{3.0, -2.0})); image.addFITSKeyword({"DEC", "62.02302376908295", "Declination of the center of the image (deg)"});
image.properties.push_back(Property("PropertyComplex64", Complex64{-3.0, 2.0}));
image.fitsKeywords.push_back({"RA", "226.9751163116387", "Right ascension of the center of the image (deg)"});
image.fitsKeywords.push_back({"DEC", "62.02302376908295", "Declination of the center of the image (deg)"});
writer.writeImage(image); writer.writeImage(image);
image.imageType = Image::Flat; image.setImageType(Image::Flat);
image.dataBlock.codec = DataBlock::LZ4; image.setCompression(DataBlock::LZ4);
image.dataBlock.byteShuffling = 2; image.setByteshuffling(true);
writer.writeImage(image); writer.writeImage(image);
QByteArray data; QByteArray data;
std::cout << "Saving image" << std::endl; std::cout << "Saving image" << std::endl;
@@ -66,9 +63,10 @@ int main(int argc, char **argv)
reader.open(data); reader.open(data);
const Image &img0 = reader.getImage(0); const Image &img0 = reader.getImage(0);
const Image &img1 = reader.getImage(1); const Image &img1 = reader.getImage(1);
TEST(image.properties.size() != img0.properties.size(), "Property count doesn't match"); auto &prop0 = img0.imageProperties();
TEST(image.dataBlock.data != img0.dataBlock.data, "Images doesn't match"); TEST(image.imageProperties().size() != img0.imageProperties().size(), "Property count doesn't match");
TEST(img0.dataBlock.data != img1.dataBlock.data, "Images doesn't match"); //TEST(image.imageDataSize() != img0._dataBlock.data, "Images doesn't match");
//TEST(img0._dataBlock.data != img1._dataBlock.data, "Images doesn't match");
} }
else if(argc == 2 && argv[1] == QString("bench")) else if(argc == 2 && argv[1] == QString("bench"))
{ {
@@ -81,13 +79,13 @@ int main(int argc, char **argv)
TEST(reader.imagesCount() != 1, "No image"); TEST(reader.imagesCount() != 1, "No image");
const LibXISF::Image &image = reader.getImage(0); const LibXISF::Image &image = reader.getImage(0);
TEST(image.width != 8, "Invalid width") TEST(image.width() != 8, "Invalid width")
TEST(image.height != 10, "Invalid height"); TEST(image.height() != 10, "Invalid height");
TEST(image.colorSpace != LibXISF::Image::Gray, "Invalid color space"); TEST(image.colorSpace() != LibXISF::Image::Gray, "Invalid color space");
TEST(image.pixelStorage != LibXISF::Image::Planar, "Invalid pixel storage"); TEST(image.pixelStorage() != LibXISF::Image::Planar, "Invalid pixel storage");
//TEST(image.dataBlock.codec != LibXISF::DataBlock::None, "Invalid compression codec"); TEST(image.compression() != LibXISF::DataBlock::None, "Invalid compression codec");
TEST(!image.dataBlock.embedded, "Not embedded"); //TEST(!image.dataBlock.embedded, "Not embedded");
TEST(image.dataBlock.data.size() != 80*2, "Invalid data size"); TEST(image.imageDataSize() != 80*2, "Invalid data size");
} }
} }
catch (const LibXISF::Error &e) catch (const LibXISF::Error &e)