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* 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; }