Ejemplo n.º 1
0
/** A simple routine to read an AmiraMesh file
    that defines a scalar/vector field on a uniform grid.
*/
float* LoadField(const char* FileName, 
	int* xDim, int* yDim, int* zDim, 
	float* xmin, float* ymin, float* zmin, 
	float* xmax, float* ymax, float* zmax)
{
	float* pData = NULL;
    FILE* fp = fopen(FileName, "rb");
    if (!fp)
    {
        printf("Could not find %s\n", FileName);
        return NULL;
    }

    printf("Reading %s\n", FileName);

    //We read the first 2k bytes into memory to parse the header.
    //The fixed buffer size looks a bit like a hack, and it is one, but it gets the job done.
    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"))
    {
        printf("Not a proper AmiraMesh file.\n");
        fclose(fp);
        return NULL;
    }

    //Find the Lattice definition, i.e., the dimensions of the uniform grid    
    sscanf(FindAndJump(buffer, "define Lattice"), "%d %d %d", xDim, yDim, zDim);
    printf("\tGrid Dimensions: %d %d %d\n", *xDim, *yDim, *zDim);

    //Find the BoundingBox    
    sscanf(FindAndJump(buffer, "BoundingBox"), "%g %g %g %g %g %g", xmin, xmax, ymin, ymax, zmin, zmax);
    printf("\tBoundingBox in x-Direction: [%g ... %g]\n", *xmin, *xmax);
    printf("\tBoundingBox in y-Direction: [%g ... %g]\n", *ymin, *ymax);
    printf("\tBoundingBox in z-Direction: [%g ... %g]\n", *zmin, *zmax);

    //Is it a uniform grid? We need this only for the sanity check below.
    const bool bIsUniform = (strstr(buffer, "CoordType \"uniform\"") != NULL);
    printf("\tGridType: %s\n", 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);
    }
    printf("\tNumber of Components: %d\n", 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);
        return NULL;
    }

    //Find the beginning of the data section
    const long idxStartData = strstr(buffer, "# Data section follows") - buffer;
    if (idxStartData > 0)
    {
        //Set the file pointer to the beginning of "# Data section follows"
        fseek(fp, idxStartData, SEEK_SET);
        //Consume this line, which is "# Data section follows"
        fgets(buffer, 2047, fp);
        //Consume the next line, which is "@1"
        fgets(buffer, 2047, fp);

        //Read the data
        // - how much to read
        const size_t NumToRead = *xDim * *yDim * *zDim * NumComponents;
        // - prepare memory; use malloc() if you're using pure C
        pData = new float[NumToRead];
        if (pData)
        {
            // - do it
            const size_t ActRead = fread((void*)pData, sizeof(float), NumToRead, fp);
            // - ok?
            if (NumToRead != ActRead)
            {
                printf("Something went wrong while reading the binary data section.\nPremature end of file?\n");
                delete[] pData;
                fclose(fp);
                return NULL;
            }

			/*
            //Test: Print all data values
            //Note: Data runs x-fastest, i.e., the loop over the x-axis is the innermost
            printf("\nPrinting all values in the same order in which they are in memory:\n");
            int Idx(0);
            for(int k=0;k<zDim;k++)
            {
                for(int j=0;j<yDim;j++)
                {
                    for(int i=0;i<xDim;i++)
                    {
                        //Note: Random access to the value (of the first component) of the grid point (i,j,k):
                        // pData[((k * yDim + j) * xDim + i) * NumComponents]
                        assert(pData[((k * yDim + j) * xDim + i) * NumComponents] == pData[Idx * NumComponents]);

                        for(int c=0;c<NumComponents;c++)
                        {
                            printf("%g ", pData[Idx * NumComponents + c]);
                        }
                        printf("\n");
                        Idx++;
                    }
                }
            }

            delete[] pData; */
        }
    }

    fclose(fp);
	return pData;
}
Ejemplo n.º 2
0
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);
    }
}