/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkMemoryLimitImageDataStreamer.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkMemoryLimitImageDataStreamer.h" #include "vtkAlgorithmOutput.h" #include "vtkCommand.h" #include "vtkExtentTranslator.h" #include "vtkImageData.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkObjectFactory.h" #include "vtkPipelineSize.h" #include "vtkStreamingDemandDrivenPipeline.h" vtkCxxRevisionMacro(vtkMemoryLimitImageDataStreamer, "$Revision: 1.12 $"); vtkStandardNewMacro(vtkMemoryLimitImageDataStreamer); //---------------------------------------------------------------------------- vtkMemoryLimitImageDataStreamer::vtkMemoryLimitImageDataStreamer() { // Set a default memory limit of 50 Megabytes this->MemoryLimit = 50000; } //---------------------------------------------------------------------------- void vtkMemoryLimitImageDataStreamer::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "MemoryLimit (in kb): " << this->MemoryLimit << endl; } //---------------------------------------------------------------------------- int vtkMemoryLimitImageDataStreamer ::ProcessRequest(vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector) { if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) { if (this->CurrentDivision == 0) { // we must set the extent on the input vtkInformation* outInfo = outputVector->GetInformationObject(0); // get the requested update extent int outExt[6]; outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), outExt); vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); vtkImageData *input = vtkImageData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); vtkExtentTranslator *translator = this->GetExtentTranslator(); translator->SetWholeExtent(outExt); vtkPipelineSize *sizer = vtkPipelineSize::New(); this->NumberOfStreamDivisions = 1; unsigned long oldSize, size = 0; float ratio; translator->SetPiece(0); // watch for the limiting case where the size is the maximum size // represented by an unsigned long. In that case we do not want to do // the ratio test. We actual test for size < 0.5 of the max unsigned // long which would indicate that oldSize is about at max unsigned // long. unsigned long maxSize; maxSize = (((unsigned long)0x1) << (8*sizeof(unsigned long) - 1)); // we also have to watch how many pieces we are creating. Since // NumberOfStreamDivisions is an int, it cannot be more that say 2^31 // (which is a bit much anyhow) so we also stop if the number of pieces // is too large. int count = 0; // double the number of pieces until the size fits in memory // or the reduction in size falls to 20% do { oldSize = size; translator->SetNumberOfPieces(this->NumberOfStreamDivisions); translator->PieceToExtentByPoints(); int inExt[6]; translator->GetExtent(inExt); // set the update extent inInfo->Set( vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6); // then propagate it vtkAlgorithm *alg = input->GetProducerPort()->GetProducer(); int index = input->GetProducerPort()->GetIndex(); vtkStreamingDemandDrivenPipeline *exec = vtkStreamingDemandDrivenPipeline::SafeDownCast(alg->GetExecutive()); exec->PropagateUpdateExtent(index); size = sizer->GetEstimatedSize(this,0,0); // watch for the first time through if (!oldSize) { ratio = 0.5; } // otherwise the normal ratio calculation else { ratio = size/(float)oldSize; } this->NumberOfStreamDivisions = this->NumberOfStreamDivisions*2; count++; } while (size > this->MemoryLimit && (size < maxSize && ratio < 0.8) && count < 29); // undo the last *2 this->NumberOfStreamDivisions = this->NumberOfStreamDivisions/2; sizer->Delete(); } return this->Superclass::ProcessRequest(request, inputVector, outputVector); } return this->Superclass::ProcessRequest(request, inputVector, outputVector); }