Url Url::ResolveReference(const Url& ref) const { if (ref.IsAbsolute()) return ref; Url url; url.SetScheme(m_strScheme); url.SetUser(m_strUserName); url.SetPassword(m_strPassword); url.SetHost(m_strHost); url.SetPort(m_iPort); url.SetRawQuery(ref.GetRawQuery()); url.SetFragment(ref.GetFragment()); auto pathDirList = base::strings::Split(m_strPath, "/"); auto relDirList = base::strings::Split(ref.GetPath(), "/"); std::stack<std::string> pathDirStack; for (auto v : pathDirList) { if (v.empty()) continue; pathDirStack.push(v); } for (auto v : relDirList) { if (v.empty() || "." == v) continue; if (".." == v) { if (!pathDirStack.empty()) pathDirStack.pop(); } else pathDirStack.push(v); } if (pathDirStack.empty()) url.SetPath("/"); else { std::string strPath; while (!pathDirStack.empty()) { strPath = pathDirStack.top() + "/" + strPath; pathDirStack.pop(); } url.SetPath("/" + strPath); } return url; }
//[-------------------------------------------------------] //[ Public RTTI methods ] //[-------------------------------------------------------] bool VolumeLoaderDAT::Load(Volume &cVolume, File &cFile) { Url cObjectFilename; Vector3i vResolution; EDataFormat nFormat = DataByte; // Get the image holding the volumetric data Image &cImage = cVolume.GetVolumeImage(); { // Use the tokenizer in order to gather all required information, ignore the rest // A "dat"-file (simple ASCII) looks like this /* ObjectFileName: Teddybear.raw TaggedFileName: --- Resolution: 128 128 62 SliceThickness: 2.8 2.8 5 Format: UCHAR NbrTags: 0 ObjectType: TEXTURE_VOLUME_OBJECT ObjectModel: RGBA GridType: EQUIDISTANT */ // Startup the tokenizer Tokenizer cTokenizer; cTokenizer.Start(cFile.GetContentAsString()); // Loop through all tokens String sToken = cTokenizer.GetNextToken(); while (sToken.GetLength()) { // ObjectFileName if (sToken == "ObjectFileName:") { // The file format specification says: // "The object file name refers to the name of the data file, which contains the raw voxel data. // This can be either an absolute path or a relative path with respect to the storage position of the dat file." // Get the value cObjectFilename = cTokenizer.GetNextToken(); // Resolution } else if (sToken == "Resolution:") { // The file format specification says: // "The volume data set consists of a large array of voxel values. The resolution of the data set is given // by the number of voxels in x-, y- and z- direction." // Get the values vResolution.x = cTokenizer.GetNextToken().GetInt(); vResolution.y = cTokenizer.GetNextToken().GetInt(); vResolution.z = cTokenizer.GetNextToken().GetInt(); // SliceThickness } else if (sToken == "SliceThickness:") { // The file format specification says: // "The size of one voxel in x-, y- and z- direction (usually in millimeters)." // mm to cm cm to m static const float Scale = 0.1f * 0.01f; // Get the values Vector3 vSliceThickness; vSliceThickness.x = cTokenizer.GetNextToken().GetFloat()*Scale; vSliceThickness.y = cTokenizer.GetNextToken().GetFloat()*Scale; vSliceThickness.z = cTokenizer.GetNextToken().GetFloat()*Scale; // Set the size of one voxel (without metric, but usually one unit is equal to one meter) cVolume.SetVoxelSize(vSliceThickness); // Format } else if (sToken == "Format:") { // The file format specification says: // "The data format of one voxel. Can be either UCHAR (8 bit) or USHORT (16 bit)." // Get the value const String sFormat = cTokenizer.GetNextToken(); if (sFormat == "UCHAR") nFormat = DataByte; // Byte (8 bit) else if (sFormat == "USHORT") nFormat = DataWord; // Word (16 bit) } // Next token, please sToken = cTokenizer.GetNextToken(); } } // Valid settings? If so, open and read in the raw data... if (!cObjectFilename.IsEmpty() && vResolution.x > 0 && vResolution.y > 0 && vResolution.z > 0) { // The file format specification says: // "The data file simply contains the raw voxel data as a large binary array which is indexed as // voxel(x,y,z) = array[z * YDIM * XDIM + y * XDIM + x], // with XDIM, YDIM and ZDIM referring to the resolution of the data set, as specified in line 3 // of the header file. For 16 bit data, the data may be stored either in big endian or little endian format." // -> We expect "Little Endian First" // Get the filename of the raw file const String sRawFilename = cObjectFilename.IsAbsolute() ? cObjectFilename.GetUrl() : (cFile.GetUrl().CutFilename() + cObjectFilename.GetUrl()); // Open the raw file File cRawFile(sRawFilename); if (cRawFile.Open(File::FileRead)) { // Create image buffer ImageBuffer *pImageBuffer = cImage.CreatePart()->CreateMipmap(); pImageBuffer->CreateImage(nFormat, ColorGrayscale, vResolution); // Read the data cRawFile.Read(pImageBuffer->GetData(), 1, pImageBuffer->GetDataSize()); // Load the transfer function by using "<filename>.table", or at least try it cVolume.GetTransferFunction().LoadByFilename(cFile.GetUrl().CutExtension() + ".table"); // Done return true; } } // Error! return false; }