The expiration time for new job artifacts in CI/CD pipelines is now 30 days (GitLab default). Previously generated artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

Commit e97cf77e authored by schultezub's avatar schultezub
Browse files

* added AbstractProcessor stub

 * added MhdImageReader
 * fixed ImageDataDisk

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@168 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 299e2574
#include "abstractprocessor.h"
namespace TUMVis {
const std::string AbstractProcessor::loggerCat_ = "TUMVis.core.datastructures.Processor";
AbstractProcessor::AbstractProcessor() {
}
AbstractProcessor::~AbstractProcessor() {
}
void AbstractProcessor::addDataHandle(const std::string& name, const DataHandle* dh) {
_data.addDataHandle(name, dh);
}
const DataContainer& AbstractProcessor::getDataContainer() const {
return _data;
}
}
#ifndef PROCESSOR_H__
#define PROCESSOR_H__
#include "tgt/logmanager.h"
#include "core/datastructures/datacontainer.h"
namespace TUMVis {
/**
* Abstract base class for TUMVis Processors.
*
* \sa AbstractPipeline
*/
class AbstractProcessor {
public:
/**
* Creates a AbstractProcessor.
*/
AbstractProcessor();
/**
* Virtual Destructor
**/
virtual ~AbstractProcessor();
/**
* Execute this processor.
**/
virtual void process() = 0;
/**
* Adds the given DataHandle \a data, accessible by the key \name, to this DataContainer.
* Already existing DataHandles with the same key will be removed from this DataContainer.
*
* \param name Key for accessing the DataHandle within this DataContainer
* \param data DataHandle to add.
**/
virtual void addDataHandle(const std::string& name, const DataHandle* dh);
/**
* Returns the local DataContainer of this Processor.
* \returns Processor::_data
**/
const DataContainer& getDataContainer() const;
protected:
DataContainer _data; ///< DataContainer containing local working set of data for this Processor
static const std::string loggerCat_;
};
}
#endif // PROCESSOR_H__
#include "imagedatadisk.h"
namespace TUMVis {
const std::string ImageDataDisk::loggerCat_ = "TUMVis.core.datastructures.ImageDataDisk";
ImageDataDisk::ImageDataDisk(const std::string& url, size_t dimensionality, const tgt::svec3& size, WeaklyTypedPointer::PointerType type, size_t offset /*= 0*/, EndianHelper::Endianness endianness /*= EndianHelper::LITTLE_ENDIAN*/, const tgt::svec3& stride /*= tgt::svec2::zero */)
: ImageData(dimensionality, size)
, _url(url)
, _offset(offset)
, _endianess(endianness)
, _stride(stride)
{
}
ImageDataDisk::~ImageDataDisk() {
}
ImageData* ImageDataDisk::getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const {
tgtAssert(tgt::hand(tgt::lessThan(llf, urb)), "Coordinates in LLF must be componentwise smaller than the ones in URB!");
tgt::svec3 newSize = urb - llf;
if (newSize == _size) {
// nothing has changed, just provide a copy:
return static_cast<ImageData*>(clone());
}
size_t newOffset = _offset + WeaklyTypedPointer::numBytes(_type) * llf.x;
// the stride doesn't change!
tgt::svec3 newStride = (_stride == tgt::svec3::zero) ? getCanonicStride(_size) : _stride;
return new ImageDataDisk(_url, _dimensionality, newSize,_type, newOffset, _endianess, newStride);
}
TUMVis::WeaklyTypedPointer ImageDataDisk::getImageData() const {
size_t numElements = tgt::hmul(_size);
size_t numBytesPerElement = WeaklyTypedPointer::numBytes(_type);
size_t numBytes = numElements * numBytesPerElement;
// open file and prepare for read
std::ifstream file(_url.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
if (file.is_open()) {
size_t fileSize = file.tellg();
if (fileSize < numBytes) {
LERROR("File is smaller than expected.");
return WeaklyTypedPointer(_type, 0);
}
file.seekg(_offset, std::ios::beg);
// Reserve memory - because we have no type information we simply read into a char array.
char* data = new char[numBytes];
// handle stride:
tgt::svec3 canonicStride = getCanonicStride(_size);
if (_stride == tgt::svec3::zero || _stride == canonicStride) {
// no stride is easy - we have just one chunk of data:
file.read(data, numBytes);
}
else {
// TODO: Check for correctness when being adequately awake! ;)
size_t index = 0;
// we have a stride at at least one direction
if (_stride.z == 0 || canonicStride.z) {
if (_stride.y == 0 || canonicStride.y) {
// we have a stride only in the last dimension so we can read the elements from the first two dimension in a row
size_t sz = _size.x*_size.y;
for (size_t z = 0; z < _size.z; ++z) {
size_t posZ = static_cast<size_t>(file.tellg());
file.read(data + index, sz * numBytesPerElement);
file.seekg(posZ + (_stride.z * numBytesPerElement), std::ios::beg);
index += sz;
}
}
else {
// we have a stride only in the last 2 dimensions so we can read the elements from the first dimension in a row
for (size_t z = 0; z < _size.z; ++z) {
size_t posZ = static_cast<size_t>(file.tellg());
for (size_t y = 0; y < _size.y; ++y) {
file.read(data + index, _size.x * numBytesPerElement);
file.seekg((_stride.y - _size.x) * numBytesPerElement, std::ios::cur);
index += _size.x;
}
file.seekg(posZ + (_stride.z * numBytesPerElement), std::ios::beg);
}
}
}
else {
// read each element separately
for (size_t z = 0; z < _size.z; ++z) {
size_t posZ = static_cast<size_t>(file.tellg());
for (size_t y = 0; y < _size.y; ++y) {
size_t posY = static_cast<size_t>(file.tellg());
for (size_t x = 0; x < _size.x; ++x) {
file.read(data + index, numBytesPerElement);
file.seekg((_stride.x - 1) * numBytesPerElement, std::ios::cur);
++index;
}
file.seekg(posY + (_stride.y * numBytesPerElement), std::ios::beg);
}
file.seekg(posZ + (_stride.z * numBytesPerElement), std::ios::beg);
}
}
}
file.close();
// handle endianess
EndianHelper::Endianness localEndianess = EndianHelper::getLocalEndianness();
if (_endianess != localEndianess) {
// This is not the most beautiful design, but unfortunately swapEndian needs to know the number of bytes at compiletime...
switch (_type) {
case WeaklyTypedPointer::UCHAR:
case WeaklyTypedPointer::CHAR:
for (size_t i = 0; i < numElements; ++i)
data[i] = EndianHelper::swapEndian(data[i]);
break;
case WeaklyTypedPointer::USHORT:
case WeaklyTypedPointer::SHORT: {
short* tmp = reinterpret_cast<short*>(data);
for (size_t i = 0; i < numElements; ++i)
tmp[i] = EndianHelper::swapEndian(tmp[i]);
break;
}
case WeaklyTypedPointer::UINT:
case WeaklyTypedPointer::INT: {
int* tmp = reinterpret_cast<int*>(data);
for (size_t i = 0; i < numElements; ++i)
tmp[i] = EndianHelper::swapEndian(tmp[i]);
break;
}
case WeaklyTypedPointer::FLOAT: {
float* tmp = reinterpret_cast<float*>(data);
for (size_t i = 0; i < numElements; ++i)
tmp[i] = EndianHelper::swapEndian(tmp[i]);
break;
}
case WeaklyTypedPointer::ULONG:
case WeaklyTypedPointer::LONG: {
long* tmp = reinterpret_cast<long*>(data);
for (size_t i = 0; i < numElements; ++i)
tmp[i] = EndianHelper::swapEndian(tmp[i]);
break;
}
case WeaklyTypedPointer::DOUBLE: {
double* tmp = reinterpret_cast<double*>(data);
for (size_t i = 0; i < numElements; ++i)
tmp[i] = EndianHelper::swapEndian(tmp[i]);
break;
}
default:
tgtAssert(false, "Should not reach this!");
LERROR("Tried to swap endianess with unsupported number of bytes per element (" << numBytesPerElement << ")");
break;
}
}
return WeaklyTypedPointer(_type, static_cast<void*>(data));
}
else {
LERROR("Could not open file " << _url << " for reading.");
return WeaklyTypedPointer(_type, 0);
}
}
tgt::svec3 ImageDataDisk::getCanonicStride(const tgt::svec3& size) const {
return tgt::svec3(0, size.x, size.x * size.y);
}
AbstractData* ImageDataDisk::clone() const {
return new ImageDataDisk(_url, _dimensionality, _size, _type, _offset, _endianess, _stride);
}
}
\ No newline at end of file
......@@ -13,7 +13,7 @@ namespace TUMVis {
{
}
bool TextFileParser::hasToken(const std::string& key) const {
bool TextFileParser::hasKey(const std::string& key) const {
return (_tokens.find(key) != _tokens.end());
}
......@@ -78,6 +78,46 @@ namespace TUMVis {
}
}
size_t TextFileParser::getSizeT(const std::string& key) const throw (tgt::CorruptedFileException) {
std::string str = getString(key);
try {
return StringUtils::fromString<size_t>(str);
}
catch (std::exception& e) {
throw tgt::CorruptedFileException("Error parsing key " + key + " to size_t: " + e.what(), _url);
}
}
tgt::svec2 TextFileParser::getSvec2(const std::string& key) const throw (tgt::CorruptedFileException){
std::string str = getString(key);
try {
return StringUtils::fromString<tgt::svec2>(str);
}
catch (std::exception& e) {
throw tgt::CorruptedFileException("Error parsing key " + key + " to svec2: " + e.what(), _url);
}
}
tgt::svec3 TextFileParser::getSvec3(const std::string& key) const throw (tgt::CorruptedFileException){
std::string str = getString(key);
try {
return StringUtils::fromString<tgt::svec3>(str);
}
catch (std::exception& e) {
throw tgt::CorruptedFileException("Error parsing key " + key + " to svec3: " + e.what(), _url);
}
}
tgt::svec4 TextFileParser::getSvec4(const std::string& key) const throw (tgt::CorruptedFileException){
std::string str = getString(key);
try {
return StringUtils::fromString<tgt::svec4>(str);
}
catch (std::exception& e) {
throw tgt::CorruptedFileException("Error parsing key " + key + " to svec4: " + e.what(), _url);
}
}
float TextFileParser::getFloat(const std::string& key) const throw (tgt::CorruptedFileException) {
std::string str = getString(key);
try {
......
......@@ -59,7 +59,7 @@ namespace TUMVis {
* \param key The key to search for.
* \return True if a key-value pair with the given key is existent, otherwise false.
*/
bool hasToken(const std::string& key) const;
bool hasKey(const std::string& key) const;
/**
* Returns the value to the given key \a key.
......@@ -110,6 +110,39 @@ namespace TUMVis {
tgt::ivec4 getIvec4(const std::string& key) const throw (tgt::CorruptedFileException);
/**
* Returns the size_t representation of the value for the given key \a key.
* \param key The key to search for.
* \return size_t representation for the corresponding value to the given key.
* \throw tgt::CorruptedFileException if no such key existent or conversion failed.
*/
size_t getSizeT(const std::string& key) const throw (tgt::CorruptedFileException);
/**
* Returns the svec2 representation of the value for the given key \a key.
* \param key The key to search for.
* \return svec2 representation for the corresponding value to the given key.
* \throw tgt::CorruptedFileException if no such key existent or conversion failed.
*/
tgt::svec2 getSvec2(const std::string& key) const throw (tgt::CorruptedFileException);
/**
* Returns the svec3 representation of the value for the given key \a key.
* \param key The key to search for.
* \return svec3 representation for the corresponding value to the given key.
* \throw tgt::CorruptedFileException if no such key existent or conversion failed.
*/
tgt::svec3 getSvec3(const std::string& key) const throw (tgt::CorruptedFileException);
/**
* Returns the svec4 representation of the value for the given key \a key.
* \param key The key to search for.
* \return svec4 representation for the corresponding value to the given key.
* \throw tgt::CorruptedFileException if no such key existent or conversion failed.
*/
tgt::svec4 getSvec4(const std::string& key) const throw (tgt::CorruptedFileException);
/**
* Returns the float representation of the value for the given key \a key.
* \param key The key to search for.
......@@ -197,6 +230,8 @@ namespace TUMVis {
lines.push_back(file->getLine('\n'));
}
std::string data = StringUtils::join(lines, "\n");
file->close();
delete file;
T itemSplitter;
return itemSplitter(data);
......@@ -215,6 +250,8 @@ namespace TUMVis {
while (!file->eof()) {
lines.push_back(file->getLine());
}
file->close();
delete file;
return lines;
}
......
#include "mhdimagereader.h"
#include <fstream>
#include "tgt/filesystem.h"
#include "core/datastructures/imagedatadisk.h"
#include "core/tools/textfileparser.h"
/*
* Full format specification at http://www.itk.org/Wiki/MetaIO/Documentation
*/
namespace TUMVis {
const std::string AbstractProcessor::loggerCat_ = "TUMVis.modules.io.MhdImageReader";
MhdImageReader::MhdImageReader()
: AbstractProcessor()
{
}
MhdImageReader::~MhdImageReader() {
}
void MhdImageReader::process() {
TextFileParser tfp(_url, true, "=");
tfp.parse<TextFileParser::ItemSeparatorLines>();
std::string url;
size_t dimensionality;
tgt::svec3 size;
WeaklyTypedPointer::PointerType pt;
size_t offset = 0;
EndianHelper::Endianness e = EndianHelper::LITTLE_ENDIAN;
// start parsing
try {
// image type
if (tfp.getString("ObjectType") != "Image") {
LERROR("Error while parsing MHD header: ObjectType = Image expected");
return;
}
// dimensionality and size
dimensionality = tfp.getSizeT("NDims");
if (dimensionality == 2)
size = tgt::svec3(tfp.getSvec2("DimSize"), 0);
else if (dimensionality == 3)
size = tfp.getSvec3("DimSize");
else {
LERROR("Error while parsing MHD header: Unsupported dimensionality: " << dimensionality);
return;
}
// element type
std::string et = tfp.getString("ElementType");
if (et == "MET_UCHAR")
pt = WeaklyTypedPointer::UCHAR;
else if (et == "MET_CHAR")
pt = WeaklyTypedPointer::CHAR;
else if (et == "MET_USHORT")
pt = WeaklyTypedPointer::USHORT;
else if (et == "MET_SHORT")
pt = WeaklyTypedPointer::SHORT;
else if (et == "MET_UINT")
pt = WeaklyTypedPointer::UINT;
else if (et == "MET_INT")
pt = WeaklyTypedPointer::INT;
else if (et == "MET_FLOAT")
pt = WeaklyTypedPointer::FLOAT;
else if (et == "MET_DOUBLE")
pt = WeaklyTypedPointer::DOUBLE;
else {
LERROR("Error while parsing MHD header: Unsupported element type: " << et);
return;
}
// further optional parameters:
if (tfp.hasKey("HeaderSize")) {
// header size can be -1...
int tmp = tfp.getInt("HeaderSize");
if (tmp >= 0)
offset = static_cast<int>(tmp);
}
if (tfp.hasKey("ElementByteOrderMSB"))
e = (tfp.getBool("ElementByteOrderMSB") ? EndianHelper::BIG_ENDIAN : EndianHelper::LITTLE_ENDIAN);
// TODO: spacing, element size, etc.
// get raw image location:
url = tfp.getString("ElementDataFile");
if (url == "LOCAL") {
url = _url;
// find beginning of local data:
tgt::File* file = FileSys.open(_url);
if (!file || !file->isOpen())
throw tgt::FileException("Could not open file " + _url + " for reading.", _url);
while (!file->eof()) {
std::string line = StringUtils::trim(file->getLine());
if (line.find("ElementDataFile") == 0) {
offset = file->tell();
}
file->close();
delete file;
}
}
else if (url == "LIST") {
LERROR("Error while loading MHD file: Image list currently not supported.");
return;
}
// all parsing done - lets create the image:
ImageDataDisk* image = new ImageDataDisk(url, dimensionality, size, pt, offset, e);
_data.addData("output.image.read", image);
}
catch (tgt::Exception& e) {
LERROR("Error while parsing MHD header: " << e.what());
return;
}
catch (std::exception& e) {
LERROR("Error while parsing MHD header: " << e.what());
return;
}
}
}
\ No newline at end of file
#ifndef MHDIMAGEREADER_H__
#define MHDIMAGEREADER_H__
#include <string>
#include "core/datastructures/abstractprocessor.h"
namespace TUMVis {
/**
*
*
* \note Full format specification at http://www.itk.org/Wiki/MetaIO/Documentation
*/
class MhdImageReader : public AbstractProcessor {
public:
/**
* Constructs a new MhdImageReader Processor
**/
MhdImageReader();
/**
* Destructor
**/
virtual ~MhdImageReader();
virtual void process();
private:
void parseHeader();
// TODO make this a property as soon as the property system exists
std::string _url;
static const std::string loggerCat_;
};
}
#endif // MHDIMAGEREADER_H__
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment