예제 #1
0
SbBool 
writeImage( const char* file, unsigned int offset, SbXipImage& image )
{
#ifdef WIN32
    //assuming everything is done using the bad backslashes... so we convert all forward slashes to those
    const char * fileLocal = XipReplaceChar(file, '/', '\\').getString();
#else //UNIX
    //assuming the other way around since we need forward slashes now...
    const char * fileLocal = XipReplaceChar(file, '\\', '/').getString();
#endif //WIN32
    
	int r = 0;

	void* imageBufferPtr = image.refBufferPtr();
	if( imageBufferPtr )
	{
		SbString path = XipStrExpandEnv( fileLocal );
		FILE* fs = fopen( path.getString(), "wb" );
		if (!fs) 
			return FALSE;

		fseek( fs, offset, SEEK_SET );
		r = fwrite(imageBufferPtr, 1, image.bufferSize(), fs );

		fclose( fs );
	}
	image.unrefBufferPtr();

	return (r == image.bufferSize());
}
예제 #2
0
void SoXipDicomExaminer::updateCamera()
{
	SoXipDataImage* xipImage = ((SoXipSFDataImage *)mImage->getField(SbName("image")))->getValue();
	if( !xipImage )
		return ;

	SbXipImage* image = xipImage->get();
	if( image )
	{
		SbVec3f newImagePos = image->getModelMatrix()[3];
		
		SbVec3f oldImagePos = mImageModelMatrix[3];

		SbVec3f cameraTranslation = (newImagePos - oldImagePos);

		getCamera()->position.setValue( getCamera()->position.getValue() + cameraTranslation );
		
		mImageModelMatrix = image->getModelMatrix();
		
		SbVec3f t, s, normal;
		SbRotation r, so;
		mImageModelMatrix.getTransform(t, r, s, so);
		normal = SbVec3f(mImageModelMatrix[2][0], mImageModelMatrix[2][1], mImageModelMatrix[2][2]);
		normal.normalize();

		SbPlane plane ( normal, t );

		planeSlice.setValue ( plane ) ;
	}
}
예제 #3
0
void SoXipDicomExaminer::GLRender( SoGLRenderAction* action )
{
	if (mViewAll)
	{
		SoXipDataImage* xipImage = ((SoXipSFDataImage *)mImage->getField(SbName("image")))->getValue();
		if( !xipImage )
			return ;

		SbXipImage* image = xipImage->get();
		if( image )
			adjustCamera( action, image->getModelMatrix() );

		// Store the information of the current displayed image
		mImageModelMatrix = image->getModelMatrix();

		mViewAll = FALSE;
	}

	if( mViewBoundingBox )
	{
		adjustCamera( action, boundingBox.getValue() );

		mViewBoundingBox = false;
	}

	// Set the Dicom Element
	setElement( action );

	mImageSwitch->enableNotify( FALSE );
	((SoSFInt32 *)mImageSwitch->getField(SbName("whichChild")))->setValue( drawImage.getValue() ? 0 : -1 );
	mImageSwitch->enableNotify( TRUE );
	
	SoXipKit::GLRender( action );
}
예제 #4
0
void SoVolumeMetrics::calculateVolumeMetris()
{
	SoXipDataImage* maskData = inputVolume.getValue();
	if (!maskData || !maskData->get())
	{
		SoDebugError::postInfo(__FILE__, "input volume data is NULL");
		return;
	}

	SbXipImage* mask = maskData->get();
	SbMatrix matMask = mask->getModelMatrix();
	SbXipImageDimensions maskDimension = mask->getDimStored();

	//decompose the model matrix
	SbVec3f colVector, rowVector, norVector, volPosition;

	colVector[0] = matMask[0][0];
	colVector[1] = matMask[0][1];
	colVector[2] = matMask[0][2];

	rowVector[0] = matMask[1][0];
	rowVector[1] = matMask[1][1];
	rowVector[2] = matMask[1][2];

	norVector[0] = matMask[2][0];
	norVector[1] = matMask[2][1];
	norVector[2] = matMask[2][2];

	volPosition[0] = matMask[3][0];
	volPosition[1] = matMask[3][1];
	volPosition[2] = matMask[3][2];

	float valSpacing[3];
	valSpacing[0] = colVector.length() / (float)maskDimension[0];
	valSpacing[1] = rowVector.length() / (float)maskDimension[1];
	valSpacing[2] = norVector.length() / (float)maskDimension[2];

	double volumeFactor = 0.001*valSpacing[0]*valSpacing[1]*valSpacing[2];

	unsigned long volume=0, recist=0, who=0;
	int nSize = maskDimension[0] * maskDimension[1];
	unsigned char* pMask = (unsigned char*)mask->refBufferPtr();

	for (int k = 0; k < maskDimension[2]; k++) {
		unsigned char* pSlice = pMask + k * nSize;

		for (int j = 0; j < nSize; j++) {

			if (pSlice[j] != 0)
				volume++;
		}
	}

	_volume = (double)volume * volumeFactor;

	mask->unrefBufferPtr();
}
예제 #5
0
void SoXipImage::GLRender(SoGLRenderAction * action)
{
    try
    {
        if (!mConnectionsSet)
            mConnectionsSet = setKitConnections();

	SoXipData * eltLut = (SoXipData *)SoXipLutElement::get(action->getState());

        // If LUT presence change, or image is dirty, update texture mode
        bool updateTexMode = ((eltLut == 0) == mHasLut) || mImageDirty;

        mHasLut = (eltLut != 0);        // Rememeber if we had a LUT or not

        if (updateTexMode && mTextureMode) {
            // This is a hack to keep same behavior as previous SoXipImage
            if (mHasLut) {
                mTextureMode->set("REPLACE");
            }
            else {
                SoXipDataImage * dip = image.getValue();
                SbXipImage *     ip = dip ? dip->get() : 0;

                if (ip) {
                    if (ip->getComponents() > 2) {
                        mTextureMode->set("REPLACE");
                    }
                    else {
                        mTextureMode->set("MODULATE");
                    }
                }
            }

            mImageDirty = false;
        }

        if (mConnectionsSet)
            SoBaseKit::GLRender(action);
    }
    catch (...)
    {
        SoError::post(__FILE__, "Unknown error while rendering image");
    }
}
void SoXipImageAttributes::evaluate()
{
	SoXipDataImage *imgData = image.getValue();

	if (imgData)
	{
		SbXipImage *img = imgData->get();
		if (img)
		{
			SO_ENGINE_OUTPUT(modelMatrix, SoSFMatrix, setValue(img->getModelMatrix()));
			SO_ENGINE_OUTPUT(bitsStored, SoSFShort, setValue(img->getBitsStored()));

			SO_ENGINE_OUTPUT(width,  SoSFShort, setValue(img->getDimStored()[0]));
			SO_ENGINE_OUTPUT(height, SoSFShort, setValue(img->getDimStored()[1]));
			SO_ENGINE_OUTPUT(depth,  SoSFShort, setValue(img->getDimStored()[2]));

			SbMatrix modelMat = img->getModelMatrix();

			SbVec3f t, s;
			SbRotation r, so;
			modelMat.getTransform(t, r, s, so);
			modelMat.multVecMatrix(SbVec3f(0.5, 0.5, 0.5), t);

			// scale MPR model matrix always to max. individual dimension by default
			float maxScale = s[0] > s[1] ? s[0] : s[1] > s[2] ? s[1] : s[2];
//			modelMat.setTransform(t, r, SbVec3f(maxScale, maxScale, maxScale), so);

			// when using get/setTransform, the rotation is derived from normal vector
			// but for gantry tilt, we need to compute normal from row and column vector
			SbVec3f rot[3];
			rot[0] = SbVec3f(modelMat[0][0], modelMat[0][1], modelMat[0][2]);
			rot[1] = SbVec3f(modelMat[1][0], modelMat[1][1], modelMat[1][2]);
			rot[2] = rot[0].cross(rot[1]);

			rot[0].normalize();
			rot[1].normalize();
			rot[2].normalize();
			rot[0] *= maxScale;
			rot[1] *= maxScale;
			rot[2] *= maxScale;

			modelMat = SbMatrix(
				rot[0][0], rot[0][1], rot[0][2], 0,
				rot[1][0], rot[1][1], rot[1][2], 0,
				rot[2][0], rot[2][1], rot[2][2], 0,
				t[0], t[1], t[2], 1);

			// update engine outputs
			SbMatrix tmp = SbMatrix::identity();

			// flip default viewing direction
			tmp.setRotate(SbRotation(SbVec3f(1, 0, 0), M_PI));

			SbMatrix defOrient = tmp * modelMat;

			// adjust so plane falls onto original plane
			defOrient.getTransform(t, r, s, so);
			SbVec3f object;
			modelMat = img->getModelMatrix();
			modelMat.inverse().multVecMatrix(t, object);

			object[0] = int(object[0] * img->getDimStored()[0] + 0.5);
			object[1] = int(object[1] * img->getDimStored()[1] + 0.5);
			object[2] = int(object[2] * img->getDimStored()[2] + 0.5);

			object[0] /= img->getDimStored()[0];
			object[1] /= img->getDimStored()[1];
			object[2] /= img->getDimStored()[2];

			modelMat.multVecMatrix(object, t);
			defOrient.setTransform(t, r, s, so);

			SO_ENGINE_OUTPUT(defaultOrientation, SoSFMatrix, setValue(defOrient));

			SbMatrix ortho1, ortho2, ortho3;
			int which = XipGeomUtils::orthoOrientations(defOrient, ortho1, ortho2, ortho3);
			SO_ENGINE_OUTPUT(orthoScanOrientation, SoSFShort, setValue(which));

			SO_ENGINE_OUTPUT(orthoOrientation1, SoSFMatrix, setValue(ortho1));
			SO_ENGINE_OUTPUT(orthoOrientation2, SoSFMatrix, setValue(ortho2));
			SO_ENGINE_OUTPUT(orthoOrientation3, SoSFMatrix, setValue(ortho3));

			defOrient.getTransform(t, r, s, so);
			SO_ENGINE_OUTPUT(defaultCenter, SoSFVec3f, setValue(t));

			return;
		}
	}

	SO_ENGINE_OUTPUT(modelMatrix, SoSFMatrix, setValue(SbMatrix::identity()));
	SO_ENGINE_OUTPUT(bitsStored, SoSFShort, setValue(0));

	SO_ENGINE_OUTPUT(width,  SoSFShort, setValue(0));
	SO_ENGINE_OUTPUT(height, SoSFShort, setValue(0));
	SO_ENGINE_OUTPUT(depth,  SoSFShort, setValue(0));

	SbMatrix rot1, rot2;
	SO_ENGINE_OUTPUT(defaultOrientation, SoSFMatrix, setValue(SbMatrix::identity()));
	SO_ENGINE_OUTPUT(orthoScanOrientation, SoSFShort, setValue(0));
	SO_ENGINE_OUTPUT(orthoOrientation1, SoSFMatrix, setValue(SbMatrix::identity()));
	rot1.setRotate(SbRotation(SbVec3f(1, 0, 0), -M_PI / 2.f));
	SO_ENGINE_OUTPUT(orthoOrientation2, SoSFMatrix, setValue(rot1));
	rot2.setRotate(SbRotation(SbVec3f(0, 1, 0), M_PI / 2.f));
	SO_ENGINE_OUTPUT(orthoOrientation3, SoSFMatrix, setValue(rot2 * rot1));

	SO_ENGINE_OUTPUT(defaultCenter, SoSFVec3f, setValue(SbVec3f(0.5, 0.5, 0.5)));
}
예제 #7
0
void 
SoXipImageOperation::evaluate()
{
	try
	{
		// Reset output
		if( mMaskData )
		{
			mMaskData->unref();
			mMaskData = 0;
		}

		SO_ENGINE_OUTPUT( mask, SoXipSFDataImage, setValue(0) );

		SoXipDataImage* maskData1 = mask1.getValue();
		SoXipDataImage* maskData2 = mask2.getValue();

		if( !maskData1 || !maskData1->get() )
		{
			if( operation.getValue() == MASK_OR || operation.getValue() == MASK_NOR )
			{
				SO_ENGINE_OUTPUT( mask, SoXipSFDataImage, setValue(maskData2) );
			}
			return ;
		}
		else if( !maskData2 || !maskData2->get() )
		{
			if( operation.getValue() == MASK_OR || operation.getValue() == MASK_NOR )
			{
				SO_ENGINE_OUTPUT( mask, SoXipSFDataImage, setValue(maskData1) );
			}
			return ;
		}

		SbXipImage* maskImage1 = maskData1->get();
		SbXipImage* maskImage2 = maskData2->get();

		if( maskImage1->getType() != SbXipImage::UNSIGNED_BYTE ||
			maskImage2->getType() != SbXipImage::UNSIGNED_BYTE ||
			maskImage1->getComponentLayoutType() != SbXipImage::PACKED_LUMINANCE ||
			maskImage2->getComponentLayoutType() != SbXipImage::PACKED_LUMINANCE )
		{
			SoDebugError::post( __FILE__, "SoXipImageOperation::evaluate(): image format not supported. \
				Expect unsigned 8 bits packed image" );
			return ;
		}

		SbXipImageDimensions dimensions = maskImage1->getDimStored();

		if( maskImage2->getDimStored() != dimensions )
		{
			SoDebugError::post( __FILE__, "SoXipImageOperation::evaluate(): input masks have different dimensions" );
			return ;
		}

		// Allocate output mask
		SbXipImage* maskOut = new SbXipImage(
			dimensions,
			SbXipImage::UNSIGNED_BYTE,
			8,
			1,
			SbXipImage::SEPARATE, 
			SbXipImage::PACKED_LUMINANCE, 
			maskImage1->getModelMatrix() );

		if( !maskOut )
		{
			SoMemoryError::post( "SoXipImageOperation::evaluate(): output mask" );
			return ;
		}

		unsigned char* mask1Ptr = (unsigned char *) maskImage1->refBufferPtr();
		unsigned char* mask2Ptr = (unsigned char *) maskImage2->refBufferPtr();
		unsigned char* maskOutPtr = (unsigned char *) maskOut->refBufferPtr();
		{
			int lineLengthAllocated = maskImage1->getLineLengthAllocated();
			int numCells = dimensions[2] * dimensions[1] * lineLengthAllocated;

			if( operation.getValue() == MASK_OR )
			{
				for( int i = 0; i < numCells; ++ i )
					*maskOutPtr ++ = *mask1Ptr ++ | *mask2Ptr ++;
			}
			else if( operation.getValue() == MASK_AND )
			{
				for( int i = 0; i < numCells; ++ i )
					*maskOutPtr ++ = *mask1Ptr ++ & *mask2Ptr ++;
			}
			else if( operation.getValue() == MASK_NOR )
			{
				for( int i = 0; i < numCells; ++ i )
					*maskOutPtr ++ = *mask1Ptr ++ ^ *mask2Ptr ++;
			}				
		}
		maskImage1->unrefBufferPtr();
		maskImage2->unrefBufferPtr();
		maskOut->unrefBufferPtr();

		mMaskData = new SoXipDataImage;
		if( !mMaskData )
		{
			SoMemoryError::post( "SoXipImageOperation::evaluate(): output mask data" );
			return ;
		}

		mMaskData->ref();
		mMaskData->set( maskOut );

		SO_ENGINE_OUTPUT( mask, SoXipSFDataImage, setValue(mMaskData) );
	}
예제 #8
0
void
SoXipComposeVec6::evaluate()
{
	SO_ENGINE_OUTPUT(outVOI, SoMFInt32, setNum(6));

	// intersection of plane and volume

	SO_ENGINE_OUTPUT(outVOI, SoMFInt32, set1Value(0, xmin.getValue()) );
	SO_ENGINE_OUTPUT(outVOI, SoMFInt32, set1Value(1, xmax.getValue()) );

	SO_ENGINE_OUTPUT(outVOI, SoMFInt32, set1Value(2, ymin.getValue()) );
	SO_ENGINE_OUTPUT(outVOI, SoMFInt32, set1Value(3, ymax.getValue()) );

	SO_ENGINE_OUTPUT(outVOI, SoMFInt32, set1Value(4, zmin.getValue()) );
	SO_ENGINE_OUTPUT(outVOI, SoMFInt32, set1Value(5, zmax.getValue()) );
	
	// Reset outputs
    SO_ENGINE_OUTPUT( numSlices, SoSFShort, setValue(0) );
    SO_ENGINE_OUTPUT( output, SoXipSFDataImage, setValue(0) );

	SoXipDataImage* imageData = image.getValue();
	if( mImageData != imageData )
	{
		mImageData = image.getValue();

		// Reset previous outputs
		mOutputs.setNum(0);

		if( mImageData )
		{
			SbXipImage* image = mImageData->get();
			if( !image )
				return ;

			// Initialize outputs
			unsigned int numSlices = image->getDimStored()[2];			
			mOutputs.setNum( numSlices );

			for( unsigned int i = 0; i < numSlices; ++ i )
				mOutputs.set1Value( i, 0 );
		}
	}

	if( imageData )
	{
		SbXipImage* image = mImageData->get();
		if( !image )
			return ;

		SbXipImageDimensions dimensions = image->getDimStored();

		SbXipImageDimensions sliceDimensions = dimensions;
		sliceDimensions[2] = 1;

		int sliceIndex = this->sliceIndex.getValue();
		if( sliceIndex < 0 || sliceIndex >= dimensions[2] )
			return ;

		if( mOutputs[sliceIndex] == 0 )
		{
			// Compute the model matrix of the selected frame
			SbMatrix sliceModelMatrix = image->getModelMatrix();
			sliceModelMatrix[2][0] /= dimensions[2];
			sliceModelMatrix[2][1] /= dimensions[2];
			sliceModelMatrix[2][2] /= dimensions[2];

			sliceModelMatrix[3][0] += sliceIndex * sliceModelMatrix[2][0];
			sliceModelMatrix[3][1] += sliceIndex * sliceModelMatrix[2][1];
			sliceModelMatrix[3][2] += sliceIndex * sliceModelMatrix[2][2];

			// Pointer to the selected slice
			char* imagePtr = (char *) image->refBufferPtr();

			unsigned int cellSize;
			switch( image->getType() )
			{
			case SbXipImage::UNSIGNED_BYTE: cellSize = sizeof(unsigned char); break ;
			case SbXipImage::BYTE: cellSize = sizeof(char); break ;
			case SbXipImage::UNSIGNED_SHORT: cellSize = sizeof(unsigned short); break ;
			case SbXipImage::SHORT: cellSize = sizeof(short); break ;
			case SbXipImage::UNSIGNED_INT: cellSize = sizeof(unsigned int); break ;
			case SbXipImage::INT: cellSize = sizeof(int); break ;
			case SbXipImage::FLOAT: cellSize = sizeof(float); break ;
			case SbXipImage::DOUBLE: cellSize = sizeof(double); break ;
			}

			void* slicePtr = imagePtr + cellSize * image->getComponents() * dimensions[0] * dimensions[1] * sliceIndex;

			SbXipImage* slice = new SbXipImage( sliceDimensions, image->getType(), image->getBitsStored(), slicePtr,
				image->getComponents(), image->getComponentType(), image->getComponentLayoutType(), sliceModelMatrix,
				image->getLineAlignment() );

			image->unrefBufferPtr();

			SoXipDataImage* output = new SoXipDataImage();
			output->ref();
			output->set( slice );
			output->addRef( imageData );

			mOutputs.set1Value( sliceIndex, output );
		}

		SO_ENGINE_OUTPUT( output, SoXipSFDataImage, setValue(mOutputs[sliceIndex]) );
    }
}
예제 #9
0
void SoXipCPUMprRender::readyBuffers(SoState *state)
{
	SbXipImageDimensions dim(0, 0, 0);
	SoXipDataImage *imgData = 0;
	SbXipImage *image = 0;

	// Volume
	imgData = volume.getValue();
	dim = SbXipImageDimensions(0,0,0);
	if (imgData && (image = imgData->get()))
	{
		// If data has changed, update MPR
		if (imgData->getDataId() != mVolDataId)
		{
			mVolDataId = imgData->getDataId();
			mUpdateFlag |= UPDATE_MPR;
		}
		if (mVolDataType != image->getType() || mVolBitsUsed != image->getBitsStored())
		{
			mVolDataType = image->getType();
			mVolBitsUsed = image->getBitsStored();
			mMPRSize = SbVec2s(-1, -1); // force buffer resizing
		}
		mVolBuf = image->refBufferPtr();
		dim = imgData->get()->getDimAllocated();
		// If dimensions have changed, update Cache
		if (dim != mVolDim)
		{
			mVolDim = dim;
			mUpdateFlag |= UPDATE_MPRCACHE;
		}
	}
	else
	{
		mVolBuf = 0;
		mVolDim = dim;
		mVolDataId = 0;
	}

	// Transfer function LUT
	imgData = (SoXipDataImage *) SoXipLutElement::get(state);
	if (imgData && (image = imgData->get()) &&
		image->getType() == SbXipImage::FLOAT &&
		image->getComponentLayoutType() == SbXipImage::RGBA)
	{
		// If there was no LUT before, resize buffers
		if (!mLutBuf)
			mMPRSize = SbVec2s(-1, -1);
		mLutSize = image->getDimStored()[0];
		mLutBuf = (float*) image->refBufferPtr();

		// If data has changed, update MPR
		if (imgData->getDataId() != mLutDataId)
		{
			mLutDataId = imgData->getDataId();
			mUpdateFlag |= UPDATE_MPR;
		}
	}
	else
	{
		// If there was a LUT before, force resizing
		if (mLutBuf)
			mMPRSize = SbVec2s(-1, -1);
		mLutBuf = 0;
		mLutSize = 0;
		mLutDataId = 0;
	}
}
예제 #10
0
SbXipImage* SoXipLoadBMP::loadBMP(const char *fileName)
{
    try
    {
        BMP bmp;
        bmp.ReadFromFile(fileName);

        int numBits = bmp.TellBitDepth();
        int width = bmp.TellWidth();
        int height = bmp.TellHeight();

        int bitsStored = 8;
        int samplesPerPixel = 0;
        SbXipImage::ComponentType compType = SbXipImage::INTERLEAVED;
        SbXipImage::ComponentLayoutType compLayoutType = SbXipImage::RGB;

        if(numBits<=24)
        {
            samplesPerPixel = 3;
            compLayoutType = SbXipImage::RGB;
        }
        else if(numBits == 32)
        {
            samplesPerPixel = 4;
            compLayoutType = SbXipImage::RGBA;
        }

        SbVec3f pos(0, 0, 0);
        SbVec3f scale(width, height, 1);
        SbMatrix rotMatrix(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1);

        SbMatrix modelMatrix;
        modelMatrix.setScale(scale);
        //modelMatrix.setTransform(pos, SbRotation(rotMatrix), scale);

        SbXipImage *image = new SbXipImage(SbXipImageDimensions(width, height, 1), SbXipImageDimensions(width, height, 1),
                                           SbXipImage::UNSIGNED_BYTE, bitsStored, samplesPerPixel, compType, compLayoutType, modelMatrix);
        unsigned char *buffer = (unsigned char *) image->refBufferPtr();

        if(numBits<=24)
        {
            for(int i = 0; i < height; i++)
            {
                for(int j = 0; j < width; j++)
                {
                    RGBApixel pixel = bmp.GetPixel(j,(height -1) - i );

                    buffer[3*i*width+3*j] = pixel.Red;
                    buffer[3*i*width+3*j+1] = pixel.Green;
                    buffer[3*i*width+3*j+2] = pixel.Blue;

                }
            }
        }
        else if(numBits == 32)
        {
            for(int i=0; i<height; i++)
            {
                for(int j=0; j<width; j++)
                {
                    RGBApixel pixel = bmp.GetPixel(j, height-i);

                    buffer[4*i*width+4*j] = pixel.Red;
                    buffer[4*i*width+4*j+1] = pixel.Green;
                    buffer[4*i*width+4*j+2] = pixel.Blue;
                    buffer[4*i*width+4*j+3] = pixel.Alpha;
                }
            }
        }

        image->unrefBufferPtr();

        return image;
    }
    catch(...)
    {
        SoDebugError::postInfo(__FILE__, "Exception loadBMP");

        // Fix me need to delete allocated memory!
        return 0;
    }
}