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;
}
示例#2
0
VolumeCollection* AnalyzeVolumeReader::readAnalyze(const std::string &fileName, int volId)
    throw (tgt::FileException, std::bad_alloc)
{
    LINFO("Loading analyze file " << fileName);
    LINFO("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();
    }

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

    int numVolumes = dimension.dim[4];
    LINFO("Number of volumes: " << numVolumes);

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

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

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

    std::string voreenVoxelType;
    switch(dimension.datatype) {
        case DT_UNSIGNED_CHAR:
            voreenVoxelType = "uint8";
            break;
        case DT_SIGNED_SHORT:
            voreenVoxelType = "int16";
            break;
        case DT_SIGNED_INT:
            voreenVoxelType = "int32";
            break;
        case DT_FLOAT:
            voreenVoxelType = "float";
            break;
        case DT_DOUBLE:
            voreenVoxelType = "double";
            break;
        case DT_RGB:
            voreenVoxelType = "Vector3(uint8)";
            break;
        case DT_ALL:
        case DT_COMPLEX:
        case 0: //DT_NONE/DT_UNKNOWN
        case DT_BINARY:
        default:
            throw tgt::UnsupportedFormatException("Unsupported datatype!");
    }

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

    int start = 0;
    int stop = numVolumes;
    if(volId != -1) {
        //we want to load a single volume:
        start = volId;
        stop = start + 1;
    }

    // Nifti transformations give us the center of the first voxel, we translate to correct:
    mat4 pToW = mat4::createTranslation(-spacing * 0.5f);

    VolumeCollection* vc = new VolumeCollection();
    size_t volSize = hmul(tgt::svec3(dimensions)) * (dimension.bitpix / 8);
    for(int i=start; i<stop; i++) {
        VolumeRepresentation* volume = new VolumeDisk(getRelatedImgFileName(fileName), voreenVoxelType, dimensions, i * volSize, bigEndian);
        Volume* vh = new Volume(volume, spacing, vec3(0.0f));
        vh->setOrigin(VolumeURL(fileName));
        vh->setPhysicalToWorldMatrix(pToW);

        VolumeURL origin(fileName);
        origin.addSearchParameter("volumeId", itos(i));
        vh->setOrigin(origin);

        vc->add(vh);
    }

    return vc;
}
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;
}
示例#4
0
VolumeCollection* AnalyzeVolumeReader::readNifti(const std::string &fileName, bool standalone, int volId)
    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);
    }

    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 read hdr+img Nifti as standalone!");
        standalone = false;
    }
    else
        throw tgt::CorruptedFileException("Not a Nifti header!", fileName);

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

    int numVolumes = header.dim[4];
    LINFO("Number of volumes: " << numVolumes);

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

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

    int timeunit = XYZT_TO_TIME(header.xyzt_units);
    int spaceunit = XYZT_TO_SPACE(header.xyzt_units);
    LINFO("timeunit: " << timeunit << " spaceunit: " << spaceunit);

    float dt = header.pixdim[4];
    float toffset = header.toffset;
    switch(timeunit) {
        case NIFTI_UNITS_SEC:
            dt *= 1000.0f;
            toffset *= 1000.0f;
            break;
        case NIFTI_UNITS_MSEC:
            //nothing to do
            break;
        case NIFTI_UNITS_USEC:
            dt /= 1000.0f;
            toffset /= 1000.0f;
            break;
    }

    switch(spaceunit) {
        case NIFTI_UNITS_MM:
            //nothing to do
            break;
        case NIFTI_UNITS_METER:
            spacing *= 1000.0f;
            LWARNING("Units: meter");
            break;
        case NIFTI_UNITS_MICRON:
            spacing /= 1000.0f;
            LWARNING("Units: micron");
            break;
        case NIFTI_UNITS_UNKNOWN:
        default:
            LWARNING("Unknown space unit!");
            break;
    }

    LINFO("Datatype: " << header.datatype);
    std::string voreenVoxelType = "";
    RealWorldMapping denormalize;
    bool applyRWM = header.scl_slope != 0.0f;

    switch(header.intent_code) {
        case IC_INTENT_SYMMATRIX:  /* parameter at each voxel is symmetrical matrix */
            //TODO: should be relatively easy (=> tensors)
        case IC_INTENT_DISPVECT:   /* parameter at each voxel is displacement vector */
        case IC_INTENT_VECTOR:     /* parameter at each voxel is vector */
            //TODO: should be relatively easy
        case IC_INTENT_GENMATRIX:  /* parameter at each voxel is matrix */
            //TODO: should be relatively easy
        case IC_INTENT_POINTSET:   /* value at each voxel is spatial coordinate (vertices/nodes of surface mesh) */
        case IC_INTENT_TRIANGLE:   /* value at each voxel is spatial coordinate (vertices/nodes of surface mesh) */
        case IC_INTENT_QUATERNION:
            throw tgt::UnsupportedFormatException("Unsupported intent code!");
            break;
        case IC_INTENT_ESTIMATE:   /* parameter for estimate in intent_name */
        case IC_INTENT_LABEL:      /* parameter at each voxel is index to label defined in aux_file */
        case IC_INTENT_NEURONAME:  /* parameter at each voxel is index to label in NeuroNames label set */
        case IC_INTENT_DIMLESS:    /* dimensionless value */
        case IC_INTENT_NONE:
            break;
        default:
            LWARNING("Unhandled intent code");
            break;
    }
    //if (header.intent_code == IC_INTENT_SYMMATRIX) {
        //h.objectModel_ = "TENSOR_FUSION_LOW";
    //}
    if(voreenVoxelType == "") {
        switch(header.datatype) {
            case DT_UNSIGNED_CHAR:
                voreenVoxelType = "uint8";
                denormalize = RealWorldMapping::createDenormalizingMapping<uint8_t>();
                break;
            case DT_SIGNED_SHORT:
                voreenVoxelType = "int16";
                denormalize = RealWorldMapping::createDenormalizingMapping<int16_t>();
                break;
            case DT_SIGNED_INT:
                voreenVoxelType = "int32";
                denormalize = RealWorldMapping::createDenormalizingMapping<int32_t>();
                break;
            case DT_FLOAT:
                voreenVoxelType = "float";
                break;
            case DT_DOUBLE:
                voreenVoxelType = "double";
                break;
            case DT_RGB:
                voreenVoxelType = "Vector3(uint8)";
                applyRWM = false;
                break;
            case DT_RGBA32:         /* 4 byte RGBA (32 bits/voxel)  */
                voreenVoxelType = "Vector4(uint8)";
                applyRWM = false;
                break;
            case DT_INT8:           /* signed char (8 bits)         */
                voreenVoxelType = "int8";
                break;
            case DT_UINT16:         /* unsigned short (16 bits)     */
                voreenVoxelType = "uint16";
                denormalize = RealWorldMapping::createDenormalizingMapping<uint16_t>();
                break;
            case DT_UINT32:         /* unsigned int (32 bits)       */
                voreenVoxelType = "uint32";
                denormalize = RealWorldMapping::createDenormalizingMapping<uint32_t>();
                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!");
        }
    }

    RealWorldMapping rwm(header.scl_slope, header.scl_inter, "");

    int headerskip = static_cast<uint16_t>(header.vox_offset);

    std::string rawFilename = fileName;
    if(!standalone)
        rawFilename = getRelatedImgFileName(fileName);

    mat4 pToW = mat4::identity;

    //Calculate transformation:
    if(header.sform_code > 0) {
        mat4 vToW(header.srow_x[0], header.srow_x[1], header.srow_x[2], header.srow_x[3],
                  header.srow_y[0], header.srow_y[1], header.srow_y[2], header.srow_y[3],
                  header.srow_z[0], header.srow_z[1], header.srow_z[2], header.srow_z[3],
                  0.0f, 0.0f, 0.0f, 1.0f);

        mat4 wToV = mat4::identity;
        if(!vToW.invert(wToV)) {
            LERROR("Failed to invert voxel to world matrix!");
        }

        mat4 vToP = mat4::createScale(spacing); //no offset
        pToW = vToP * wToV;
    }
    else if(header.qform_code > 0) {
        float b = header.quatern_b;
        float c = header.quatern_c;
        float d = header.quatern_d;
        float a = static_cast<float>(sqrt(1.0-(b*b+c*c+d*d)));

        mat4 rot2(a*a+b*b-c*c-d*d,   2*b*c-2*a*d,       2*b*d+2*a*c,     0.0f,
                  2*b*c+2*a*d,       a*a+c*c-b*b-d*d,   2*c*d-2*a*b,     0.0f,
                  2*b*d-2*a*c,       2*c*d+2*a*b,       a*a+d*d-c*c-b*b, 0.0f,
                  0.0f,              0.0f,              0.0f,            1.0f);

        float qfac = header.pixdim[0];
        if(fabs(qfac) < 0.1f)
            qfac = 1.0f;
        mat4 sc = mat4::createScale(vec3(1.0f, 1.0f, qfac));

        mat4 os = mat4::createTranslation(vec3(header.qoffset_x, header.qoffset_y, header.qoffset_z));
        pToW = os * rot2 * sc;
    }

    // Nifti transformations give us the center of the first voxel, we translate to correct:
    pToW = pToW * mat4::createTranslation(-spacing * 0.5f);

    VolumeCollection* vc = new VolumeCollection();
    size_t volSize = hmul(tgt::svec3(dimensions)) * (header.bitpix / 8);

    int start = 0;
    int stop = numVolumes;
    if(volId != -1) {
        //we want to load a single volume:
        start = volId;
        stop = start + 1;
    }

    for(int i=start; i<stop; i++) {
        VolumeRepresentation* volume = new VolumeDisk(rawFilename, voreenVoxelType, dimensions, headerskip + (i * volSize), bigEndian);
        Volume* vh = new Volume(volume, spacing, vec3(0.0f));

        VolumeURL origin(fileName);
        origin.addSearchParameter("volumeId", itos(i));
        vh->setOrigin(origin);

        vh->setPhysicalToWorldMatrix(pToW);
        vh->setMetaDataValue<StringMetaData>("Description", std::string(header.descrip));
        //vh->addMetaData("ActualFrameDuration", new IntMetaData(ih_.frame_duration));
        //vh->addMetaData("FrameTime", new IntMetaData(ih_.frame_start_time));
        vh->setMetaDataValue<IntMetaData>("FrameTime", static_cast<int>(toffset + (i * dt)));
        if(applyRWM)
            vh->setRealWorldMapping(RealWorldMapping::combine(denormalize, rwm));

        vc->add(vh);
    }

    return vc;
}