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()); }
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 ) ; } }
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 ); }
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(); }
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))); }
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) ); }
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]) ); } }
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; } }
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; } }