Example #1
0
VolumeCollection* RawVoxVolumeReader::read(const std::string &url)
throw (tgt::CorruptedFileException, tgt::IOException, std::bad_alloc)
{
    VolumeURL origin(url);
    std::string fileName = origin.getPath();

    LINFO("Reading file " << fileName);

    std::fstream fin(fileName.c_str(), std::ios::in | std::ios::binary);
    if (!fin.good())
        throw tgt::IOException();

    RawVoxHeader header;
    fin.read(reinterpret_cast<char*>(&header), sizeof(header));
    svec3 dimensions = svec3(header.sizeX_, header.sizeY_, header.sizeZ_);

    if(header.magic_ != 1381388120) {
        throw tgt::CorruptedFileException("Wrong magic number.");
    }

    VolumeRAM* dataset;
    switch(header.bitsPerVoxel_) {
    case 8:
        LINFO("Reading 8 bit dataset");
        dataset = new VolumeRAM_UInt8(dimensions);
        break;
    case 16:
        LINFO("Reading 16 bit dataset");
        dataset = new VolumeRAM_UInt16(dimensions);
        break;
    case 32:
        LINFO("Reading 32 bit (float) dataset");
        dataset = new VolumeRAM_Float(dimensions);
        break;
    default:
        LERROR("Unknown bpp!");
        throw tgt::UnsupportedFormatException("Unexpected bpp.");
    }

    fin.read(reinterpret_cast<char*>(dataset->getData()), dataset->getNumBytes());

    if ( fin.eof() ) {
        delete dataset;
        throw tgt::CorruptedFileException();
    }

    fin.close();

    VolumeCollection* volumeCollection = new VolumeCollection();
    Volume* volumeHandle = new Volume(dataset, vec3(1.0f), vec3(0.0f));
    oldVolumePosition(volumeHandle);
    volumeHandle->setOrigin(fileName);
    volumeCollection->add(volumeHandle);

    return volumeCollection;
}
Example #2
0
VolumeCollection* FlowReader::read(const std::string& url)
    throw(tgt::FileException, std::bad_alloc)
{
    VolumeOrigin origin(url);
    std::string fileName = origin.getPath();

    LINFO("reading flow file '" << fileName << "'...");

    // try to open the file
    //
    std::fstream ifs(fileName.c_str(), std::ios_base::in | std::ios_base::binary);
    if (ifs.good() == false)
        throw tgt::IOException("Unable to open flow file for reading", fileName);

    // read the magic number (string "VOREENFLOW")
    //
    char magicNumber[11] = {0};
    ifs.read(magicNumber, 11);
    std::string temp(magicNumber);
    if (temp != "VOREENFLOW")
        throw tgt::IOException("Missing magic number in flow file", fileName);

    // read file version (must currently be 1 or 2)
    //
    unsigned int fileVersion = 0;
    ifs.read(reinterpret_cast<char*>(&fileVersion), sizeof(unsigned int));
    LINFO("file version: " << fileVersion);
    if ((fileVersion < 1) || (fileVersion > 2))
        throw tgt::IOException("Unsupported file version of flow file", fileName);

    // read flow dimension (usually 3 for 3D flows)
    //
    unsigned int flowDimension = 0;
    ifs.read(reinterpret_cast<char*>(&flowDimension), sizeof(unsigned int));
    LINFO("flow dimension: " << flowDimension << "D");
    if (flowDimension != 3)
        throw tgt::IOException("Unsupported flow dimension in flow file", fileName);

    unsigned char dataOrientation = 0;
    unsigned char reverseSlicesMask = 0;

    ifs.read(reinterpret_cast<char*>(&dataOrientation), sizeof(unsigned char));
    if (fileVersion > 1) {
        ifs.read(reinterpret_cast<char*>(&reverseSlicesMask), sizeof(unsigned char));
    }

    // read the dimension of the volume data containing the flow
    //
    tgt::ivec3 dimensions;
    ifs.read(reinterpret_cast<char*>(&dimensions), sizeof(tgt::ivec3));
    LINFO("volume dimensions: " << dimensions);

    unsigned int byteSize = 0;
    ifs.read(reinterpret_cast<char*>(&byteSize), sizeof(unsigned int));
    LINFO("expected size of vector field: " << byteSize << " byte");

    VolumeFlow3D* volume = readConvert(dimensions, dataOrientation, ifs);
    ifs.close();

    if (volume == 0) {
        LERROR("an error occured during reading flow data! Proceeding impossible.");
        return 0;
    }

    if (reverseSlicesMask != 0)
        reverseSlices(volume, reverseSlicesMask);

    // TODO: volume container merge
    /*VolumeSet* volumeSet = new VolumeSet(fileName);
    VolumeSeries* volumeSeries = new VolumeSeries(Modality::MODALITY_FLOW.getName(),
                                                  Modality::MODALITY_FLOW);
    volumeSet->addSeries(volumeSeries);
    VolumeHandle* volumeHandle = new VolumeHandle(volume, 0.0f);

    volumeSeries->addVolumeHandle(volumeHandle); */

    VolumeCollection* collection = new VolumeCollection();
    VolumeHandle* volumeHandle = new VolumeHandle(volume, tgt::vec3(1.0f), tgt::vec3(0.0f));//FIXME: spacing?
    oldVolumePosition(volumeHandle);
    volumeHandle->setModality(Modality::MODALITY_FLOW);
    collection->add(volumeHandle);

    // TODO: origin does not save series and timestamp anymore
    //volumeHandle->setOrigin(fileName, Modality::MODALITY_FLOW.getName(), 0.0f);
    volumeHandle->setOrigin(fileName);

    return collection;
}
Example #3
0
void VolumeIOHelper::loadRawVolume(const std::string& filenameStd) {

    QString filename = QString::fromStdString(filenameStd);
    if (filename.isEmpty())
        return;

    // query raw parameters via dialog
    std::string objectModel;
    std::string format;
        int numFrames;
    tgt::ivec3 dim;
    tgt::vec3 spacing;
    int headerSkip;
    bool bigEndian;
    tgt::mat4 trafoMat = tgt::mat4::identity;
    RawVolumeWidget* rawVW = new RawVolumeWidget(parent_, tr("Please enter the properties for <br><strong>") + filename + "</strong>",
        objectModel, format, numFrames, dim, spacing, headerSkip, bigEndian, trafoMat);
    if (!rawVW->exec() == QDialog::Accepted)
        return;

    // derive expected file size from provided properties
    uint formatBytes = 1;;
    if (format == "USHORT" || format == "USHORT_12" || format == "SHORT")
        formatBytes = 2;
    else if (format == "FLOAT")
        formatBytes = 4;
    else if (format == "UINT" || format == "INT")
        formatBytes = 4;

    int numChannels = 1;
    if (objectModel == "RGB")
        numChannels = 3;
    else if (objectModel == "RGBA")
        numChannels = 4;
    else if (objectModel.find("TENSOR_") == 0)
        numChannels = 6;

    uint rawSize = headerSkip + formatBytes * numChannels * (dim.x * dim.y * dim.z) * numFrames;

    // inform/query user, if file size does not match
    if (QFile(filename).size() != rawSize) {
        QMessageBox::StandardButton retButton = QMessageBox::Yes;
        if(QFile(filename).size() > rawSize) {
            QString msg = tr("The provided properties result in a size smaller\nthan the actual file size. Do you want to continue?");
            retButton = QMessageBox::question(parent_, tr("Size mismatch"), msg,
                QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
        }
        else if (QFile(filename).size() < rawSize) {
            QString msg = tr("The provided properties result in a size\ngreater than the actual file size.");
            retButton = QMessageBox::warning(parent_, tr("Size mismatch"), msg,
                QMessageBox::Cancel);
        }
        if (retButton != QMessageBox::Yes && retButton != QMessageBox::Ok)
            return;
    }

    qApp->processEvents();

    // load raw volume
    try {
        for (int frame=0; frame < numFrames; ++frame) {
            RawVolumeReader rawReader(progressBar_);
            rawReader.setReadHints(dim, spacing, objectModel, format, frame, headerSkip, bigEndian);
            VolumeList* collection = rawReader.read(filename.toStdString());
            if (collection && !collection->empty()) {
                tgtAssert(collection->size() == 1, "More than one raw volume returned");
                Volume* volumeHandle = static_cast<Volume*>(collection->first());
                oldVolumePosition(volumeHandle);
                volumeHandle->setPhysicalToWorldMatrix(trafoMat);
                volumeHandle->setTimestep(static_cast<float>(frame));
                emit(volumeLoaded(volumeHandle));
            }
            delete collection;
        }
    }
    catch (const tgt::FileException& e) {
        LERROR(e.what());
        QErrorMessage* errorMessageDialog = new QErrorMessage(VoreenApplicationQt::qtApp()->getMainWindow());
        errorMessageDialog->showMessage(e.what());
    }
    catch (std::bad_alloc&) {
        LERROR("bad allocation while reading file: " << filename.toStdString());
        QErrorMessage* errorMessageDialog = new QErrorMessage(VoreenApplicationQt::qtApp()->getMainWindow());
        errorMessageDialog->showMessage("Bad allocation while reading file: " + filename);
    }
}
VolumeCollection* AnalyzeVolumeReader::readAnalyze(const std::string &fileName)
    throw (tgt::FileException, std::bad_alloc)
{
    LWARNING("Loading analyze file " << fileName);
    LWARNING("Related img file: " << getRelatedImgFileName(fileName));

    std::ifstream file(fileName.c_str(), std::ios::in | std::ios::binary);
    if(!file) {
        throw tgt::FileNotFoundException("Failed to open file: ", fileName);
    }

    file.seekg(0, std::ios::end);
    std::streamoff fileSize = file.tellg();
    file.seekg(0, std::ios::beg);

    if(fileSize != 348)
        LWARNING("Filesize != 348");

    header_key header;
    if (!file.read((char*)&header, sizeof(header))) {
        throw tgt::CorruptedFileException("Failed to read header!", fileName);
    }

    image_dimension dimension;
    if (!file.read((char*)&dimension, sizeof(dimension))) {
        throw tgt::CorruptedFileException("Failed to read dimensions!", fileName);
    }

    data_history history;
    if (!file.read((char*)&history, sizeof(history))) {
        throw tgt::CorruptedFileException("Failed to read history!", fileName);
    }

    bool bigEndian = false;
    //check if swap is necessary:
    if((dimension.dim[0] < 0) || (dimension.dim[0] > 15)) {
        bigEndian = true;
        header.swapEndianess();
        dimension.swapEndianess();
        history.swapEndianess();
    }

    RawVolumeReader::ReadHints h;

    h.dimensions_.x = dimension.dim[1];
    h.dimensions_.y = dimension.dim[2];
    h.dimensions_.z = dimension.dim[3];
    LINFO("Resolution: " << h.dimensions_);

    if (hor(lessThanEqual(h.dimensions_, ivec3(0)))) {
        LERROR("Invalid resolution or resolution not specified: " << h.dimensions_);
        throw tgt::CorruptedFileException("error while reading data", fileName);
    }

    h.spacing_.x = dimension.pixdim[1];
    h.spacing_.y = dimension.pixdim[2];
    h.spacing_.z = dimension.pixdim[3];
    LINFO("Spacing: " << h.spacing_);

    LINFO("Datatype: " << dimension.datatype);

    switch(dimension.datatype) {
        case DT_UNSIGNED_CHAR:
            h.format_ = "UCHAR";
            h.objectModel_ = "I";
            break;
        case DT_SIGNED_SHORT:
            h.format_ = "SHORT";
            h.objectModel_ = "I";
            break;
        case DT_SIGNED_INT:
            h.format_ = "INT";
            h.objectModel_ = "I";
            break;
        case DT_FLOAT:
            h.format_ = "FLOAT";
            h.objectModel_ = "I";
            break;
        case DT_DOUBLE:
            h.format_ = "DOUBLE";
            h.objectModel_ = "I";
            break;
        case DT_RGB:
            h.format_ = "UCHAR";
            h.objectModel_ = "RGB";
            break;
        case DT_ALL:
        case DT_COMPLEX:
        case 0: //DT_NONE/DT_UNKNOWN
        case DT_BINARY:
        default:
            throw tgt::UnsupportedFormatException("Unsupported datatype!");
    }

    h.bigEndianByteOrder_ = bigEndian;

    std::string objectType;
    std::string gridType;

    RawVolumeReader rawReader(getProgressBar());
    rawReader.setReadHints(h);

    VolumeCollection* volumeCollection = rawReader.read(getRelatedImgFileName(fileName));

    if (!volumeCollection->empty()) {
        static_cast<VolumeHandle*>(volumeCollection->first())->setOrigin(VolumeOrigin(fileName));
        oldVolumePosition(static_cast<VolumeHandle*>(volumeCollection->first()));
    }

    return volumeCollection;
}
VolumeCollection* AnalyzeVolumeReader::readNifti(const std::string &fileName, bool standalone)
    throw (tgt::FileException, std::bad_alloc)
{
    LINFO("Loading nifti file " << fileName);

    std::ifstream file(fileName.c_str(), std::ios::in | std::ios::binary);
    if(!file) {
        throw tgt::FileNotFoundException("Failed to open file: ", fileName);
    }

    //file.seekg(0, std::ios::end);
    //int fileSize = file.tellg();
    //file.seekg(0, std::ios::beg);

    nifti_1_header header;
    if (!file.read((char*)&header, sizeof(header))) {
        throw tgt::CorruptedFileException("Failed to read header!", fileName);
    }

    file.close();

    bool bigEndian = false;
    //check if swap is necessary:
    if((header.dim[0] < 0) || (header.dim[0] > 15)) {
        bigEndian = true;
        header.swapEndianess();
    }

    if(header.sizeof_hdr != 348) {
        throw tgt::CorruptedFileException("Invalid header.sizeof_hdr", fileName);
    }

    if(!( (header.magic[0] == 'n') && (header.magic[2] == '1') && (header.magic[3] == 0) ))
        throw tgt::CorruptedFileException("Not a Nifti header!", fileName);

    if(header.magic[1] == '+') {
        if(!standalone)
            LWARNING("Tried to read standalone Nifti as hdr+img!");
        standalone = true;
    }
    else if(header.magic[1] == 'i') {
        if(!standalone)
            LWARNING("Tried to hdr+img Nifti as standalone!");
        standalone = false;
    }
    else
        throw tgt::CorruptedFileException("Not a Nifti header!", fileName);

    RawVolumeReader::ReadHints h;

    h.dimensions_.x = header.dim[1];
    h.dimensions_.y = header.dim[2];
    h.dimensions_.z = header.dim[3];
    LINFO("Resolution: " << h.dimensions_);

    if (hor(lessThanEqual(h.dimensions_, ivec3(0)))) {
        LERROR("Invalid resolution or resolution not specified: " << h.dimensions_);
        throw tgt::CorruptedFileException("error while reading data", fileName);
    }

    h.spacing_.x = header.pixdim[1];
    h.spacing_.y = header.pixdim[2];
    h.spacing_.z = header.pixdim[3];
    LINFO("Spacing: " << h.spacing_);

    LINFO("Datatype: " << header.datatype);

    //TODO: support more datatypes
    if(header.datatype > 128) {
        header.datatype -= 128;
        h.objectModel_ = "RGB";
    }
    else
        h.objectModel_ = "I";


    switch(header.datatype) {
        case DT_UNSIGNED_CHAR:
            h.format_ = "UCHAR";
            h.objectModel_ = "I";
            break;
        case DT_SIGNED_SHORT:
            h.format_ = "SHORT";
            h.objectModel_ = "I";
            break;
        case DT_SIGNED_INT:
            h.format_ = "INT";
            h.objectModel_ = "I";
            break;
        case DT_FLOAT:
            h.format_ = "FLOAT";
            h.objectModel_ = "I";
            break;
        case DT_DOUBLE:
            h.format_ = "DOUBLE";
            h.objectModel_ = "I";
            break;
        case DT_RGB:
            h.format_ = "UCHAR";
            h.objectModel_ = "RGB";
            break;
        case DT_RGBA32:         /* 4 byte RGBA (32 bits/voxel)  */
            h.format_ = "UCHAR";
            h.objectModel_ = "RGBA";
            break;
        case DT_INT8:           /* signed char (8 bits)         */
            h.format_ = "CHAR";
            h.objectModel_ = "I";
            break;
        case DT_UINT16:         /* unsigned short (16 bits)     */
            h.format_ = "USHORT";
            h.objectModel_ = "I";
            break;
        case DT_UINT32:         /* unsigned int (32 bits)       */
            h.format_ = "UINT";
            h.objectModel_ = "I";
            break;
        case DT_INT64:          /* long long (64 bits)          */
        case DT_UINT64:         /* unsigned long long (64 bits) */
        case DT_FLOAT128:       /* long double (128 bits)       */
        case DT_COMPLEX128:     /* double pair (128 bits)       */
        case DT_COMPLEX256:     /* long double pair (256 bits)  */
        case DT_ALL:
        case DT_COMPLEX:
        case 0: //DT_NONE/DT_UNKNOWN
        case DT_BINARY:
        default:
            throw tgt::UnsupportedFormatException("Unsupported datatype!");
    }

    if (header.intent_code == IC_INTENT_SYMMATRIX) {
        h.objectModel_ = "TENSOR_FUSION_LOW";
    }

    h.bigEndianByteOrder_ = bigEndian;

    //std::string objectType;
    //std::string gridType;
        //} else if (type == "ObjectType:") {
            //args >> objectType;
            //LDEBUG(type << " " << objectType);
        //} else if (type == "GridType:") {
            //args >> gridType;
            //LDEBUG(type << " " << gridType);
        //} else if (type == "BitsStored:") {
            //args >> h.bitsStored_;
            //LDEBUG(type << " " << h.bitsStored_);
        //} else if (type == "Unit:") {
            //args >> h.unit_;
            //LDEBUG(type << " " << h.unit_);

    if (standalone)
        h.headerskip_ = static_cast<uint16_t>(header.vox_offset);

    RawVolumeReader rawReader(getProgressBar());
    rawReader.setReadHints(h);

    VolumeCollection* volumeCollection = 0;
    if(standalone)
        volumeCollection = rawReader.read(fileName);
    else
        volumeCollection = rawReader.read(getRelatedImgFileName(fileName));

    if (!volumeCollection->empty()) {
        static_cast<VolumeHandle*>(volumeCollection->first())->setOrigin(VolumeOrigin(fileName));
        oldVolumePosition(static_cast<VolumeHandle*>(volumeCollection->first()));
    }

    return volumeCollection;
}
VolumeList* AmiraMeshReader::readMetaFile(const std::string &fileName, size_t firstSlice, size_t lastSlice, int timeframe)
    throw (tgt::FileException, std::bad_alloc)
{
	bool error = false;
	const char* FileName = fileName.c_str();
	FILE* fp = fopen(FileName, "rb");
    if (!fp)
    {
        LERROR("Could not find :" << FileName);
        error = true;
		goto K;
    }

    char buffer[2048];
    fread(buffer, sizeof(char), 2047, fp);
    buffer[2047] = '\0'; //The following string routines prefer null-terminated strings

    if (!strstr(buffer, "# AmiraMesh BINARY-LITTLE-ENDIAN 2.1") && !strstr(buffer, "# AmiraMesh 3D BINARY 2.0"))
    {
        LERROR("Not a proper AmiraMesh file.");
        fclose(fp);
        error = true;
		goto K;
    }

    //Find the Lattice definition, i.e., the dimensions of the uniform grid
    int xDim(0), yDim(0), zDim(0);
    sscanf(FindAndJump(buffer, "define Lattice"), "%d %d %d", &xDim, &yDim, &zDim);
	LDEBUG("Grid Dimensions: " << xDim << " " << yDim << " " << zDim);

    //Find the BoundingBox
    float xmin(1.0f), ymin(1.0f), zmin(1.0f);
    float xmax(-1.0f), ymax(-1.0f), zmax(-1.0f);
    sscanf(FindAndJump(buffer, "BoundingBox"), "%g %g %g %g %g %g", &xmin, &xmax, &ymin, &ymax, &zmin, &zmax);
    LDEBUG("BoundingBox in x-Direction: [" << xmin << " " << xmax << "]");
	LDEBUG("BoundingBox in x-Direction: [" << ymin << " " << ymax << "]");
	LDEBUG("BoundingBox in x-Direction: [" << zmin << " " << zmax << "]");
	
    //Is it a uniform grid? We need this only for the sanity check below.
    const bool bIsUniform = (strstr(buffer, "CoordType \"uniform\"") != NULL);
    LDEBUG("GridType: " << bIsUniform ? "uniform" : "UNKNOWN");

    //Type of the field: scalar, vector
    int NumComponents(0);
    if (strstr(buffer, "Lattice { float Data }"))
    {
        //Scalar field
        NumComponents = 1;
    }
    else
    {
        //A field with more than one component, i.e., a vector field
        sscanf(FindAndJump(buffer, "Lattice { float["), "%d", &NumComponents);
    }
    LDEBUG("Number of Components: " << NumComponents);

    //Sanity check
    if (xDim <= 0 || yDim <= 0 || zDim <= 0
        || xmin > xmax || ymin > ymax || zmin > zmax
        || !bIsUniform || NumComponents <= 0)
    {
        printf("Something went wrong\n");
        fclose(fp);
        error = true;
		goto K;
    }


	K : RawVolumeReader::ReadHints h;
	std::string objectFilename = fileName;

	h.headerskip_ = strstr(buffer, "# Data section follows") - buffer;
    //Set the file pointer to the beginning of "# Data section follows"
	fseek(fp, h.headerskip_, SEEK_SET);
    //Consume this line, which is "# Data section follows"
	char buf1[2048];
	fgets(buf1, 2047, fp);
	int l1 = strlen(buf1);

    //Consume the next line, which is "@1"
	char buf2[2048];
    fgets(buf2, 2047, fp);
	int l2 = strlen(buf2);

    vec3 sliceThickness = vec3(1.f, 1.f, 1.f);
    int numFrames = NumComponents;
	
	h.dimensions_.x = xDim;
	h.dimensions_.y = yDim;
	h.dimensions_.z = zDim;
	
	h.format_ = "FLOAT";
	h.objectModel_ = "I";
	h.bigEndianByteOrder_ = false;
	h.headerskip_ += (l1 + l2);
	LDEBUG("Header size : " << h.headerskip_);

    if (hor(lessThanEqual(h.dimensions_, ivec3(0)))) {
        LERROR("Invalid resolution or resolution not specified: " << h.dimensions_);
        error = true;
    }

    h.spacing_ = sliceThickness;
	h.timeStep_ = 0;

	if (!error) {
        RawVolumeReader rawReader(getProgressBar());

        // do we have a relative path?
        if ((objectFilename.substr(0, 1) != "/")  && (objectFilename.substr(0, 1) != "\\") &&
            (objectFilename.substr(1, 2) != ":/") && (objectFilename.substr(1, 2) != ":\\"))
        {
            size_t p = fileName.find_last_of("\\/");
            // construct path relative to dat file
            objectFilename = fileName.substr(0, p + 1) + objectFilename;
        }

        int start = 0;
        int end = numFrames;
        if (timeframe != -1) {
            if (timeframe >= numFrames)
                throw tgt::FileException("Specified time frame not in volume", fileName);

            start = timeframe;
            end = timeframe+1;
        }

        VolumeList* toReturn = new VolumeList();
        for (int frame = start; frame < end; ++frame) {
            h.timeframe_ = frame;
            rawReader.setReadHints(h);

            VolumeList* volumeList = rawReader.readSlices(objectFilename, firstSlice, lastSlice);
            if (!volumeList->empty()) {
                VolumeURL origin(fileName);
                origin.addSearchParameter("timeframe", itos(frame));

                Volume* vh = static_cast<Volume*>(volumeList->first());
                vh->setOrigin(origin);
                vh->setTimestep(static_cast<float>(frame));

                oldVolumePosition(vh);

                if(!h.hash_.empty())
                    vh->setHash(h.hash_);

                toReturn->add(volumeList->first());
            }
            delete volumeList;
        }
        return toReturn;
    }
    else {
        throw tgt::CorruptedFileException("error while reading data", fileName);
    }
}