/*========================================================================= Program: Visualization Toolkit Module: vtkImageExport.cxx 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 "vtkImageExport.h" #include "vtkAlgorithmOutput.h" #include "vtkExecutive.h" #include "vtkImageData.h" #include "vtkInformation.h" #include "vtkMatrix3x3.h" #include "vtkObjectFactory.h" #include "vtkStreamingDemandDrivenPipeline.h" #include #include vtkStandardNewMacro(vtkImageExport); //------------------------------------------------------------------------------ vtkImageExport::vtkImageExport() { this->ImageLowerLeft = 1; this->ExportVoidPointer = nullptr; this->DataDimensions[0] = this->DataDimensions[1] = this->DataDimensions[2] = 0; this->LastPipelineMTime = 0; this->SetNumberOfOutputPorts(0); } //------------------------------------------------------------------------------ vtkImageExport::~vtkImageExport() = default; //------------------------------------------------------------------------------ vtkAlgorithm* vtkImageExport::GetInputAlgorithm() { return this->GetInputConnection(0, 0) ? this->GetInputConnection(0, 0)->GetProducer() : nullptr; } //------------------------------------------------------------------------------ vtkInformation* vtkImageExport::GetInputInformation() { return this->GetExecutive()->GetInputInformation(0, 0); } //------------------------------------------------------------------------------ void vtkImageExport::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "ImageLowerLeft: " << (this->ImageLowerLeft ? "On\n" : "Off\n"); } vtkImageData* vtkImageExport::GetInput() { if (this->GetNumberOfInputConnections(0) < 1) { return nullptr; } return vtkImageData::SafeDownCast(this->GetExecutive()->GetInputData(0, 0)); } //------------------------------------------------------------------------------ vtkIdType vtkImageExport::GetDataMemorySize() { vtkImageData* input = this->GetInput(); if (input == nullptr) { return 0; } this->GetInputAlgorithm()->UpdateInformation(); vtkInformation* inInfo = this->GetInputInformation(); int* extent = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); int size = input->GetScalarSize(); size *= input->GetNumberOfScalarComponents(); size *= (extent[1] - extent[0] + 1); size *= (extent[3] - extent[2] + 1); size *= (extent[5] - extent[4] + 1); return size; } //------------------------------------------------------------------------------ void vtkImageExport::GetDataDimensions(int* dims) { vtkImageData* input = this->GetInput(); if (input == nullptr) { dims[0] = dims[1] = dims[2] = 0; return; } this->GetInputAlgorithm()->UpdateInformation(); vtkInformation* inInfo = this->GetInputInformation(); int* extent = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); dims[0] = extent[1] - extent[0] + 1; dims[1] = extent[3] - extent[2] + 1; dims[2] = extent[5] - extent[4] + 1; } //------------------------------------------------------------------------------ void vtkImageExport::SetExportVoidPointer(void* ptr) { if (this->ExportVoidPointer == ptr) { return; } this->ExportVoidPointer = ptr; this->Modified(); } //------------------------------------------------------------------------------ // This is the superclasses style of Execute method. Convert it into // an imaging style Execute method. int vtkImageExport::RequestData(vtkInformation* vtkNotUsed(request), vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* vtkNotUsed(outputVector)) { // we are the end of the pipeline, we do nothing return 1; } //------------------------------------------------------------------------------ // Exports all the data from the input. void vtkImageExport::Export(void* output) { void* ptr = this->GetPointerToData(); if (!ptr) { // GetPointerToData() outputs an error message. return; } if (this->ImageLowerLeft) { memcpy(output, ptr, this->GetDataMemorySize()); } else { // flip the image when it is output int* extent = this->GetInputInformation()->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); int xsize = extent[1] - extent[0] + 1; int ysize = extent[3] - extent[2] + 1; int zsize = extent[5] - extent[4] + 1; int csize = this->GetInput()->GetScalarSize() * this->GetInput()->GetNumberOfScalarComponents(); for (vtkIdType i = 0; i < zsize; i++) { ptr = static_cast(static_cast(ptr) + ysize * xsize * csize); for (vtkIdType j = 0; j < ysize; j++) { ptr = static_cast(static_cast(ptr) - xsize * csize); memcpy(output, ptr, xsize * csize); output = static_cast(static_cast(output) + xsize * csize); } ptr = static_cast(static_cast(ptr) + ysize * xsize * csize); } } } //------------------------------------------------------------------------------ // Provides a valid pointer to the data (only valid until the next // update, though) void* vtkImageExport::GetPointerToData() { // Error checking if (this->GetInput() == nullptr) { vtkErrorMacro(<< "Export: Please specify an input!"); return nullptr; } vtkImageData* input = this->GetInput(); vtkAlgorithm* inpAlgorithm = this->GetInputAlgorithm(); inpAlgorithm->UpdateInformation(); inpAlgorithm->ReleaseDataFlagOff(); inpAlgorithm->UpdateWholeExtent(); this->UpdateProgress(0.0); this->UpdateProgress(1.0); return input->GetScalarPointer(); } //------------------------------------------------------------------------------ void* vtkImageExport::GetCallbackUserData() { return this; } vtkImageExport::UpdateInformationCallbackType vtkImageExport::GetUpdateInformationCallback() const { return &vtkImageExport::UpdateInformationCallbackFunction; } vtkImageExport::PipelineModifiedCallbackType vtkImageExport::GetPipelineModifiedCallback() const { return &vtkImageExport::PipelineModifiedCallbackFunction; } vtkImageExport::WholeExtentCallbackType vtkImageExport::GetWholeExtentCallback() const { return &vtkImageExport::WholeExtentCallbackFunction; } vtkImageExport::SpacingCallbackType vtkImageExport::GetSpacingCallback() const { return &vtkImageExport::SpacingCallbackFunction; } vtkImageExport::OriginCallbackType vtkImageExport::GetOriginCallback() const { return &vtkImageExport::OriginCallbackFunction; } vtkImageExport::DirectionCallbackType vtkImageExport::GetDirectionCallback() const { return &vtkImageExport::DirectionCallbackFunction; } vtkImageExport::ScalarTypeCallbackType vtkImageExport::GetScalarTypeCallback() const { return &vtkImageExport::ScalarTypeCallbackFunction; } vtkImageExport::NumberOfComponentsCallbackType vtkImageExport::GetNumberOfComponentsCallback() const { return &vtkImageExport::NumberOfComponentsCallbackFunction; } vtkImageExport::PropagateUpdateExtentCallbackType vtkImageExport::GetPropagateUpdateExtentCallback() const { return &vtkImageExport::PropagateUpdateExtentCallbackFunction; } vtkImageExport::UpdateDataCallbackType vtkImageExport::GetUpdateDataCallback() const { return &vtkImageExport::UpdateDataCallbackFunction; } vtkImageExport::DataExtentCallbackType vtkImageExport::GetDataExtentCallback() const { return &vtkImageExport::DataExtentCallbackFunction; } vtkImageExport::BufferPointerCallbackType vtkImageExport::GetBufferPointerCallback() const { return &vtkImageExport::BufferPointerCallbackFunction; } //------------------------------------------------------------------------------ void vtkImageExport::UpdateInformationCallbackFunction(void* userData) { static_cast(userData)->UpdateInformationCallback(); } int vtkImageExport::PipelineModifiedCallbackFunction(void* userData) { return static_cast(userData)->PipelineModifiedCallback(); } int* vtkImageExport::WholeExtentCallbackFunction(void* userData) { return static_cast(userData)->WholeExtentCallback(); } double* vtkImageExport::SpacingCallbackFunction(void* userData) { return static_cast(userData)->SpacingCallback(); } double* vtkImageExport::OriginCallbackFunction(void* userData) { return static_cast(userData)->OriginCallback(); } double* vtkImageExport::DirectionCallbackFunction(void* userData) { return static_cast(userData)->DirectionCallback(); } const char* vtkImageExport::ScalarTypeCallbackFunction(void* userData) { return static_cast(userData)->ScalarTypeCallback(); } int vtkImageExport::NumberOfComponentsCallbackFunction(void* userData) { return static_cast(userData)->NumberOfComponentsCallback(); } void vtkImageExport::PropagateUpdateExtentCallbackFunction(void* userData, int* extent) { static_cast(userData)->PropagateUpdateExtentCallback(extent); } void vtkImageExport::UpdateDataCallbackFunction(void* userData) { static_cast(userData)->UpdateDataCallback(); } int* vtkImageExport::DataExtentCallbackFunction(void* userData) { return static_cast(userData)->DataExtentCallback(); } void* vtkImageExport::BufferPointerCallbackFunction(void* userData) { return static_cast(userData)->BufferPointerCallback(); } //------------------------------------------------------------------------------ void vtkImageExport::UpdateInformationCallback() { if (this->GetInputAlgorithm()) { this->GetInputAlgorithm()->UpdateInformation(); } } int vtkImageExport::PipelineModifiedCallback() { if (!this->GetInput()) { return 0; } vtkMTimeType mtime = 0; if (this->GetInputAlgorithm()) { vtkExecutive* e = this->GetInputAlgorithm()->GetExecutive(); if (e) { e->ComputePipelineMTime( nullptr, e->GetInputInformation(), e->GetOutputInformation(), -1, &mtime); } } if (mtime > this->LastPipelineMTime) { this->LastPipelineMTime = mtime; return 1; } return 0; } int* vtkImageExport::WholeExtentCallback() { static int defaultextent[6] = { 0 }; if (!this->GetInputAlgorithm()) { return defaultextent; } else { return this->GetInputInformation()->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); } } double* vtkImageExport::SpacingCallback() { static double defaultspacing[3] = { 0.0 }; if (this->GetInputAlgorithm()) { return this->GetDataSpacing(); } else if (!this->GetInput()) { return defaultspacing; } else { return this->GetInput()->GetSpacing(); } } double* vtkImageExport::OriginCallback() { static double defaultorigin[3] = { 0.0 }; if (this->GetInputAlgorithm()) { return this->GetDataOrigin(); } else if (!this->GetInput()) { return defaultorigin; } else { return this->GetInput()->GetOrigin(); } } double* vtkImageExport::DirectionCallback() { static double defaultdirection[3] = { 0.0 }; if (this->GetInputAlgorithm()) { return this->GetDataDirection(); } else if (!this->GetInput()) { return defaultdirection; } else { return this->GetInput()->GetDirectionMatrix()->GetData(); } } const char* vtkImageExport::ScalarTypeCallback() { if (!this->GetInput()) { return "unsigned char"; } int scalarType; if (this->GetInputAlgorithm()) { scalarType = this->GetDataScalarType(); } else { scalarType = this->GetInput()->GetScalarType(); } switch (scalarType) { case VTK_DOUBLE: { return "double"; } case VTK_FLOAT: { return "float"; } case VTK_LONG: { return "long"; } case VTK_UNSIGNED_LONG: { return "unsigned long"; } case VTK_INT: { return "int"; } case VTK_UNSIGNED_INT: { return "unsigned int"; } case VTK_SHORT: { return "short"; } case VTK_UNSIGNED_SHORT: { return "unsigned short"; } case VTK_CHAR: { return "char"; } case VTK_UNSIGNED_CHAR: { return "unsigned char"; } case VTK_SIGNED_CHAR: { return "signed char"; } default: { return ""; } } } int vtkImageExport::NumberOfComponentsCallback() { if (!this->GetInput()) { return 1; } else if (this->GetInputAlgorithm()) { return this->GetDataNumberOfScalarComponents(); } else { return this->GetInput()->GetNumberOfScalarComponents(); } } void vtkImageExport::PropagateUpdateExtentCallback(int* extent) { if (this->GetInputAlgorithm()) { int port = this->GetInputConnection(0, 0)->GetIndex(); vtkInformation* info = this->GetInputAlgorithm()->GetOutputInformation(port); info->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent, 6); } } void vtkImageExport::UpdateDataCallback() { if (this->GetInputAlgorithm()) { this->GetInputAlgorithm()->Update(); } } int* vtkImageExport::DataExtentCallback() { static int defaultextent[6] = { 0, 0, 0, 0, 0, 0 }; if (this->GetInputAlgorithm()) { return this->GetDataExtent(); } if (!this->GetInput()) { return defaultextent; } else { return this->GetInput()->GetExtent(); } } void* vtkImageExport::BufferPointerCallback() { if (!this->GetInput()) { return static_cast(nullptr); } else { return this->GetInput()->GetScalarPointer(); } } int vtkImageExport::GetDataNumberOfScalarComponents() { if (this->GetInputAlgorithm() == nullptr) { return 1; } this->GetInputAlgorithm()->UpdateInformation(); return vtkImageData::GetNumberOfScalarComponents(this->GetExecutive()->GetInputInformation(0, 0)); } int vtkImageExport::GetDataScalarType() { if (this->GetInputAlgorithm() == nullptr) { return VTK_UNSIGNED_CHAR; } this->GetInputAlgorithm()->UpdateInformation(); return vtkImageData::GetScalarType(this->GetExecutive()->GetInputInformation(0, 0)); } int* vtkImageExport::GetDataExtent() { static int defaultextent[6] = { 0, 0, 0, 0, 0, 0 }; if (this->GetInputAlgorithm() == nullptr) { return defaultextent; } this->GetInputAlgorithm()->UpdateInformation(); return this->GetInputInformation()->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); } void vtkImageExport::GetDataExtent(int* ptr) { if (this->GetInputAlgorithm() == nullptr) { ptr[0] = ptr[1] = ptr[2] = ptr[3] = ptr[4] = ptr[5] = 0; return; } this->GetInputAlgorithm()->UpdateInformation(); this->GetInputInformation()->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), ptr); } double* vtkImageExport::GetDataSpacing() { static double defaultspacing[3] = { 1, 1, 1 }; if (this->GetInput() == nullptr) { return defaultspacing; } this->GetInputAlgorithm()->UpdateInformation(); return this->GetInputInformation()->Get(vtkDataObject::SPACING()); } void vtkImageExport::GetDataSpacing(double* ptr) { if (this->GetInputAlgorithm() == nullptr) { ptr[0] = ptr[1] = ptr[2] = 0.0; return; } this->GetInputAlgorithm()->UpdateInformation(); this->GetInputInformation()->Get(vtkDataObject::SPACING(), ptr); } double* vtkImageExport::GetDataOrigin() { static double defaultorigin[3] = { 0, 0, 0 }; if (this->GetInputAlgorithm() == nullptr) { return defaultorigin; } this->GetInputAlgorithm()->UpdateInformation(); return this->GetInputInformation()->Get(vtkDataObject::ORIGIN()); } void vtkImageExport::GetDataOrigin(double* ptr) { if (this->GetInputAlgorithm() == nullptr) { ptr[0] = ptr[1] = ptr[2] = 0.0; return; } this->GetInputAlgorithm()->UpdateInformation(); this->GetInputInformation()->Get(vtkDataObject::ORIGIN(), ptr); } double* vtkImageExport::GetDataDirection() { static double defaultdirection[9] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; if (this->GetInputAlgorithm() == nullptr) { return defaultdirection; } this->GetInputAlgorithm()->UpdateInformation(); return this->GetInputInformation()->Get(vtkDataObject::DIRECTION()); } void vtkImageExport::GetDataDirection(double* ptr) { if (this->GetInputAlgorithm() == nullptr) { ptr[0] = ptr[1] = ptr[2] = ptr[3] = ptr[4] = ptr[5] = ptr[6] = ptr[7] = ptr[8] = 0.0; return; } this->GetInputAlgorithm()->UpdateInformation(); this->GetInputInformation()->Get(vtkDataObject::DIRECTION(), ptr); }