VolumeCollection* VolumeCollection::subCollection(const std::vector<size_t>& indices) const { VolumeCollection* subCollection = new VolumeCollection(); for (size_t i=0; i<indices.size(); i++) { tgtAssert(indices.at(i) < volumeHandles_.size(), "invalid index"); subCollection->add(volumeHandles_.at(indices.at(i))); } return subCollection; }
voreen::VolumeCollection* VolumeCollection::selectOrigin(const VolumeOrigin& origin) const { VolumeCollection* collection = new VolumeCollection(); for (size_t i=0; i<volumeHandles_.size(); ++i) { if (volumeHandles_[i]->getOrigin() == origin) collection->add(volumeHandles_[i]); } return collection; }
voreen::VolumeCollection* VolumeCollection::selectOriginTimestep(const VolumeOrigin& origin, float timestep) const { VolumeCollection* collection = new VolumeCollection(); for (size_t i=0; i<volumeHandles_.size(); ++i) { VolumeHandle* vh = dynamic_cast<VolumeHandle*>(volumeHandles_[i]); if (vh && vh->getOrigin() == origin && vh->getTimestep() == timestep) collection->add(volumeHandles_[i]); } return collection; }
voreen::VolumeCollection* VolumeCollection::selectOrigin(const VolumeURL& origin) const { VolumeCollection* collection = new VolumeCollection(); for (size_t i=0; i<volumeHandles_.size(); ++i) { Volume* vh = dynamic_cast<Volume*>(volumeHandles_[i]); if (vh && vh->getOrigin() == origin) collection->add(volumeHandles_[i]); } return collection; }
VolumeCollection* VolumeCollection::subCollection(size_t start, size_t end) const { VolumeCollection* subCollection = new VolumeCollection(); tgtAssert(start <= end, "invalid indices"); tgtAssert(start < volumeHandles_.size(), "invalid start index"); tgtAssert(end < volumeHandles_.size(), "invalid end index"); for (size_t index = start; index <= end; index++) subCollection->add(volumeHandles_.at(index)); return subCollection; }
VolumeCollection* VolumeCollection::selectTimestep(float timestep) const { VolumeCollection* collection = new VolumeCollection(); for (size_t i=0; i<volumeHandles_.size(); ++i) { if (volumeHandles_[i]->getTimestep() == timestep) collection->add(volumeHandles_[i]); } return collection; }
VolumeCollection* VolumeCollection::selectModality(const Modality& modality) const { VolumeCollection* collection = new VolumeCollection(); for (size_t i=0; i<volumeHandles_.size(); ++i) { if (volumeHandles_[i]->getModality() == modality) collection->add(volumeHandles_[i]); } return collection; }
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; }
VolumeCollection* MultiVolumeReader::read(const std::string& url) throw (tgt::FileException, std::bad_alloc) { LINFO("Loading multi volume file " << url); VolumeURL urlOrigin(url); std::vector<VolumeURL> origins = listVolumes(url); if (origins.empty()) throw tgt::FileException("No volumes listed in multi-volume file", url); VolumeCollection* volumeCollection = new VolumeCollection(); std::string refFile = urlOrigin.getSearchParameter("file"); if (refFile == "") { // no particular file specified in URL => load all listed ones for (size_t i=0; i<origins.size(); i++) { VolumeBase* handle = read(origins.at(i)); if (handle) volumeCollection->add(handle); } } else { // load specified file for (size_t i=0; i<origins.size(); i++) { if (origins.at(i).getSearchParameter("file") == refFile) { VolumeBase* handle = read(origins.at(i)); if (handle) { volumeCollection->add(handle); break; } } } if (volumeCollection->empty()) { delete volumeCollection; throw tgt::FileException("File '" + refFile + "' not listed in multi-volume file", urlOrigin.getPath()); } } return volumeCollection; }
VolumeCollection* VvdVolumeReader::read(const std::string &url) throw (tgt::FileException, std::bad_alloc) { VolumeURL origin(url); std::string fileName = origin.getPath(); // open file for reading std::fstream fileStream(fileName.c_str(), std::ios_base::in); if (fileStream.fail()) { throw tgt::FileException("Failed to open file '" + tgt::FileSystem::absolutePath(fileName) + "' for reading."); } // read data stream into deserializer XmlDeserializer d(fileName); d.setUseAttributes(true); try { d.read(fileStream); } catch (SerializationException& e) { throw tgt::FileException("SerializationException: Failed to read serialization data stream from file '" + fileName + "': " + e.what()); } catch (...) { throw tgt::FileException("Failed to read serialization data stream from file '" + fileName + "' (unknown exception)."); } std::vector<VvdObject> vec; // deserialize from data stream try { d.deserialize("Volumes", vec, "Volume"); } catch (std::exception& e) { throw tgt::FileException("Deserialization from file '" + fileName + "' failed: " + e.what()); } catch (...) { throw tgt::FileException("Deserialization from file '" + fileName + "' failed (unknown exception)."); } if (vec.empty()) throw tgt::FileException("Deserialization from file '" + fileName + "' failed: no volume found"); VolumeCollection* vc = new VolumeCollection(); for(size_t i=0; i<vec.size(); i++) { Volume* vh = vec[i].createVolume(tgt::FileSystem::dirName(fileName)); vh->setOrigin(origin); vc->add(vh); } return vc; }
VolumeCollection* TransFuncListProperty::getVolumes(bool selectedOnly /*= true*/) const { VolumeCollection* collection = new VolumeCollection(); std::vector<std::string> urls = get(); for (size_t i=0; i<urls.size(); i++) { std::string url = urls.at(i); if (handleMap_.find(url) != handleMap_.end()) { if (!selectedOnly || (selectionMap_.find(url) != selectionMap_.end() && selectionMap_.find(url)->second == true) ) { VolumeBase* handle = handleMap_.find(url)->second; tgtAssert(handle, "handleMap_ contains null pointer"); collection->add(handle); } } } return collection; }
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; }
VolumeCollection* MRCVolumeReader::read(const std::string &url) throw (tgt::FileException, tgt::IOException, std::bad_alloc) { VolumeCollection* volumeCollection = new VolumeCollection(); VolumeURL origin(url); std::string fileName = origin.getPath(); LINFO(fileName); std::ifstream mrc; mrc.open(fileName.c_str(), std::ios::binary); if (!mrc.is_open()) { LWARNING("Can't open stream"); } else { int dim[3]; // grid dimensions i.e. numbers of voxels for each dimension mrc.read((char*)(&dim), sizeof(dim)); std::cout << "X: " << dim[0] << std::endl; // number of columns (fastest changing in map) std::cout << "Y: " << dim[1] << std::endl; // number of rows std::cout << "Z: " << dim[2] << std::endl; // number of sections (slowest changing in map) int numVoxels = dim[0] * dim[1] * dim[2]; // total number of voxels in volume std::cout << "numVoxels: " << numVoxels << std::endl; int dataType; // see below mrc.read((char*)(&dataType), sizeof(dataType)); std::cout << "dataType: " << dataType << std::endl; int dataSize = 0; // i.e. 8-bit, 16-bit or 32-bit if (dataType == 0) dataSize = 1; // signed 8-bit bytes range -128 to 127 else if (dataType == 1) dataSize = 2; // 16-bit halfwords else if (dataType == 2) dataSize = 4; // 32-bit reals else if (dataType == 6) dataSize = 2; // unsigned 16-bit range 0 to 65535 tgtAssert(dataSize, "Datasize is 0 at MRCVolumeReader::read()"); int totalDataSize = dataSize * numVoxels; int start[3]; // numbers of first columns i.e. offset of the volume origin in voxel coordinates mrc.read((char*)(&start), sizeof(start)); std::cout << "startX: " << start[0] << std::endl; // number of columns (fastest changing in map) std::cout << "startY: " << start[1] << std::endl; // number of rows std::cout << "startZ: " << start[2] << std::endl; // number of sections (slowest changing in map) int gridSize[3]; mrc.read((char*)(&gridSize), sizeof(gridSize)); std::cout << "gridSizeX: " << gridSize[0] << std::endl; std::cout << "gridSizeY: " << gridSize[1] << std::endl; std::cout << "gridSizeZ: " << gridSize[2] << std::endl; float cellDimensions[3]; // cell dimensions in angstroms mrc.read((char*)(&cellDimensions), sizeof(cellDimensions)); std::cout << "cellX: " << cellDimensions[0] << std::endl; std::cout << "cellY: " << cellDimensions[1] << std::endl; std::cout << "cellZ: " << cellDimensions[2] << std::endl; float scale[3]; // pixelSpacing i.e. scale from voxel to real-word coordinates scale[0] = cellDimensions[0] / gridSize[0]; scale[1] = cellDimensions[1] / gridSize[1]; scale[2] = cellDimensions[2] / gridSize[2]; std::cout << "pixelSpacingX: " << scale[0] << std::endl; std::cout << "pixelSpacingY: " << scale[1] << std::endl; std::cout << "pixelSpacingZ: " << scale[2] << std::endl; float angles[3]; // cell angles in degrees mrc.read((char*)(&angles), sizeof(angles)); std::cout << "cellAngleX: " << angles[0] << std::endl; std::cout << "cellAngleY: " << angles[1] << std::endl; std::cout << "cellAngleZ: " << angles[2] << std::endl; int axes[3]; // Which axis corresponds to columns, rows and sections (1,2,3 for X,Y,Z) mrc.read((char*)(&axes), sizeof(axes)); std::cout << "axesX: " << axes[0] << std::endl; std::cout << "axesY: " << axes[1] << std::endl; std::cout << "axesZ: " << axes[2] << std::endl; float origin[3]; mrc.seekg(4*49, std::ios::beg); mrc.read((char*)(&origin), sizeof(origin)); std::cout << "originX: " << origin[0] << std::endl; std::cout << "originY: " << origin[1] << std::endl; std::cout << "originZ: " << origin[2] << std::endl; void* data = malloc(totalDataSize); mrc.seekg(1024, std::ios::beg); mrc.read((char*)data, totalDataSize); mrc.close(); VolumeRAM* targetDataset; int a = axes[0]-1; int b = axes[1]-1; int c = axes[2]-1; /**/ if (dataType == 0) { targetDataset = new VolumeAtomic<int8_t>(ivec3(dim[a], dim[b], dim[c])); fillVolume<int8_t>(targetDataset, data, dim, axes); } else if (dataType == 1) { targetDataset = new VolumeAtomic<int16_t>(ivec3(dim[a], dim[b], dim[c])); fillVolume<int16_t>(targetDataset, data, dim, axes); } else if (dataType == 2) { targetDataset = new VolumeAtomic<float>(ivec3(dim[a], dim[b], dim[c])); fillVolume<float>(targetDataset, data, dim, axes); } else if (dataType == 6) { targetDataset = new VolumeAtomic<uint16_t>(ivec3(dim[a], dim[b], dim[c])); fillVolume<uint16_t>(targetDataset, data, dim, axes); } else LERROR("Unsupported data type at MRCVolumeReader::read()"); free(data); angles[0] *= (PI / 180.); angles[1] *= (PI / 180.); angles[2] *= (PI / 180.); float row[3][3]; // X row[0][0] = 1; row[0][1] = 0; row[0][2] = 0; // Y row[1][0] = cos(angles[2]); // cos(gamma) row[1][1] = sin(angles[2]); // sin(gamma) row[1][2] = 0; // Z row[2][0] = cos(angles[1]); // cos(beta) row[2][1] = (cos(angles[0]) - row[2][0] * row[1][0]) / row[1][1]; // [cos(alpha) - cos(beta)*cos(gamma)] / sin(gamma) row[2][2] = sqrt(1 - row[2][0] * row[2][0] - row[2][1] * row[2][1]); // squared length is 1 tgt::Matrix4<float> transform ( row[0][0], row[1][0], row[2][0], 0, row[0][1], row[1][1], row[2][1], 0, row[0][2], row[1][2], row[2][2], 0, 0.0f, 0.0f, 0.0f, 1.0f ); Volume* volumeHandle = new MoleculeVolume( targetDataset, // data vec3(scale[a], scale[b], scale[c]), // scale vec3(start[a]*scale[a], start[b]*scale[b], start[c]*scale[c]), // offset transform // transform ); volumeCollection->add(volumeHandle); } if (!volumeCollection->empty()) volumeCollection->first()->setOrigin(VolumeURL(fileName)); return volumeCollection; }
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; }
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* PVMVolumeReader::read(const std::string &url) throw (tgt::FileException, tgt::IOException, std::bad_alloc) { VolumeOrigin origin(url); std::string fileName = origin.getPath(); uint8_t* data; uint8_t* tmpData; unsigned int width, height, depth, components; float scalex, scaley, scalez; unsigned char *description; unsigned char *courtesy; unsigned char *parameter; unsigned char *comment; LINFO("Reading PVM volume " << fileName); /* TODO This subroutine returns an array created with malloc but it should be created with 'new[]' because this chunk of data will be deleted with 'delete[]'. This can cause hard to find errors. As a temporary workaround the data are copied over into a new array and the c-array is deleted with 'free'. Because of some c-pointer vodoo done in ddsbase.cpp free must be invoked after the use of all other returned pointers. (roland) */ tmpData = readPVMvolume(const_cast<char*>(fileName.c_str()), getProgressBar(), &width, &height, &depth, &components, &scalex, &scaley, &scalez, &description, &courtesy, ¶meter, &comment); if (!tmpData) { LERROR("PVM Reading failed"); return 0; } data = new uint8_t[width * height * depth * components]; memcpy(data, tmpData, width * height * depth * components); Volume* dataset = 0; if (!data) { throw tgt::IOException(); } else { LINFO("Size: " << width << " x " << height << " x " << depth); LINFO("Spacing: " << scalex << " x " << scaley << " x " << scalez); LINFO("Components: " << components); if (description) LINFO("Description: " << description); if (courtesy) LINFO("Courtesy: " << courtesy); if (parameter) LINFO("Parameter: " << parameter); if (comment) LINFO("Comment: " << comment); if (components == 1) { LINFO("Create 8 bit data set."); dataset = new VolumeUInt8(data, tgt::ivec3(width, height, depth), tgt::vec3(scalex, scaley, scalez)); } else if (components == 2) { // the endianness conversion in ddsbase.cpp seem to be broken, // so we perform it here instead uint16_t* data16 = reinterpret_cast<uint16_t*>(data); int numElements = width * height * depth; uint16_t maxValue = 0; for (int i=0; i < numElements; i++) { endian_swap(data16[i]); if (data16[i] > maxValue) maxValue = data16[i]; } int bits; if (maxValue < 4096) { LINFO("Create 12 bit data set."); bits = 12; } else { LINFO("Create 16 bit data set."); bits = 16; } dataset = new VolumeUInt16((uint16_t*)data, tgt::ivec3(width, height, depth), tgt::vec3(scalex, scaley, scalez), tgt::mat4::identity, bits); } else LERROR("Bit depth not supported."); } // TODO now it is safe to free free(tmpData); VolumeCollection* volumeCollection = new VolumeCollection(); if (dataset) { VolumeHandle* volumeHandle = new VolumeHandle(dataset, 0.0f); volumeHandle->setOrigin(VolumeOrigin(fileName)); volumeCollection->add(volumeHandle); } return volumeCollection; }
VolumeCollection* ITKVolumeReader::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); //Get OutputInformation of an arbitrary reader to find out pixel type etc: typedef itk::Image<char,3> TestImageType; // pixel type doesn't matter for current purpose typedef itk::ImageFileReader<TestImageType> TestFileReaderType; // reader for testing a file TestFileReaderType::Pointer onefileReader = TestFileReaderType::New(); onefileReader->SetFileName(fileName.c_str()); try { onefileReader->GenerateOutputInformation(); } catch(itk::ExceptionObject& excp) { throw tgt::CorruptedFileException("Failed to read OutputInformation! " + std::string(excp.GetDescription()), fileName); } // grab the ImageIO instance for the reader itk::ImageIOBase *imageIO = onefileReader->GetImageIO(); unsigned int NumberOfDimensions = imageIO->GetNumberOfDimensions(); LINFO("Number of Dimensions: " << NumberOfDimensions); if(NumberOfDimensions != 3) { throw tgt::UnsupportedFormatException("Unsupported number of dimensions!"); } // PixelType is SCALAR, RGB, RGBA, VECTOR, COVARIANTVECTOR, POINT, INDEX itk::ImageIOBase::IOPixelType pixelType = imageIO->GetPixelType(); LINFO("PixelType: " << imageIO->GetPixelTypeAsString(pixelType)); // IOComponentType is UCHAR, CHAR, USHORT, SHORT, UINT, INT, ULONG, LONG, FLOAT, DOUBLE itk::ImageIOBase::IOComponentType componentType = imageIO->GetComponentType(); LINFO("ComponentType: " << imageIO->GetComponentTypeAsString(componentType)); // NumberOfComponents is usually one, but for non-scalar pixel types, it can be anything unsigned int NumberOfComponents = imageIO->GetNumberOfComponents(); LINFO("Number of Components: " << NumberOfComponents); if(NumberOfComponents != 1) { throw tgt::UnsupportedFormatException("Unsupported number of components!"); } //-------Info we don't need here:--------------- //unsigned dims[32]; // almost always no more than 4 dims, but ... //unsigned origin[32]; double spacing[32]; //std::vector<double> directions[32]; for(unsigned i = 0; i < NumberOfDimensions && i < 32; i++) { //dims[i] = imageIO->GetDimensions(i); //origin[i] = imageIO->GetOrigin(i); spacing[i] = imageIO->GetSpacing(i); //directions[i] = imageIO->GetDirection(i); } Volume* dataset; switch(pixelType) { case itk::ImageIOBase::SCALAR: switch(componentType) { case itk::ImageIOBase::UCHAR: dataset = readScalarVolume<uint8_t>(fileName); break; case itk::ImageIOBase::CHAR: dataset = readScalarVolume<int8_t>(fileName); break; case itk::ImageIOBase::USHORT: dataset = readScalarVolume<uint16_t>(fileName); break; case itk::ImageIOBase::SHORT: dataset = readScalarVolume<int16_t>(fileName); break; case itk::ImageIOBase::UINT: dataset = readScalarVolume<uint32_t>(fileName); break; case itk::ImageIOBase::INT: dataset = readScalarVolume<int32_t>(fileName); break; #ifndef WIN32 case itk::ImageIOBase::ULONG: dataset = readScalarVolume<uint64_t>(fileName); break; case itk::ImageIOBase::LONG: dataset = readScalarVolume<int64_t>(fileName); break; #endif case itk::ImageIOBase::FLOAT: dataset = readScalarVolume<float>(fileName); break; case itk::ImageIOBase::DOUBLE: dataset = readScalarVolume<double>(fileName); break; default: throw tgt::UnsupportedFormatException("Unsupported component type!"); } break; case itk::ImageIOBase::RGB: case itk::ImageIOBase::RGBA: case itk::ImageIOBase::VECTOR: case itk::ImageIOBase::COVARIANTVECTOR: case itk::ImageIOBase::POINT: default: throw tgt::UnsupportedFormatException("Unsupported pixel type!"); return 0; } VolumeCollection* volumeCollection = new VolumeCollection(); dataset->setOrigin(fileName); volumeCollection->add(dataset); return volumeCollection; }