/*========================================================================= Program: Visualization Toolkit Module: vtkSLCReader.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 "vtkSLCReader.h" #include "vtkDataArray.h" #include "vtkImageData.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" #include "vtkStreamingDemandDrivenPipeline.h" #include #include vtkStandardNewMacro(vtkSLCReader); // Constructor for a vtkSLCReader. vtkSLCReader::vtkSLCReader() { this->FileName = nullptr; this->Error = 0; } vtkSLCReader::~vtkSLCReader() = default; // Decodes an array of eight bit run-length encoded data. unsigned char* vtkSLCReader::Decode8BitData(unsigned char* in_ptr, int size) { unsigned char* curr_ptr; unsigned char* decode_ptr; unsigned char* return_ptr; unsigned char current_value; unsigned char remaining; curr_ptr = in_ptr; decode_ptr = return_ptr = new unsigned char[size]; while (true) { current_value = *(curr_ptr++); if (!(remaining = (current_value & 0x7f))) { break; } if (current_value & 0x80) { while (remaining--) { *(decode_ptr++) = *(curr_ptr++); } } else { current_value = *(curr_ptr++); while (remaining--) { *(decode_ptr++) = current_value; } } } return return_ptr; } // This will be needed when we make this an imaging filter. int vtkSLCReader::RequestInformation( vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector) { FILE* fp; int temp; double f[3]; int size[3]; int magic_num; this->Error = 1; if (!this->FileName) { vtkErrorMacro(<< "A FileName must be specified."); return 0; } // Initialize if ((fp = vtksys::SystemTools::Fopen(this->FileName, "rb")) == nullptr) { vtkErrorMacro(<< "File " << this->FileName << " not found"); return 0; } this->FileDimensionality = 3; if (fscanf(fp, "%d", &magic_num) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to read magic number"); fclose(fp); return 1; } if (magic_num != 11111) { vtkErrorMacro(<< "SLC magic number is not correct"); fclose(fp); return 1; } f[0] = f[1] = f[2] = 0.0; this->SetDataOrigin(f); if (fscanf(fp, "%d", size) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to read size[0]"); fclose(fp); return 1; } if (fscanf(fp, "%d", size + 1) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to read size[1]"); fclose(fp); return 1; } if (fscanf(fp, "%d", size + 2) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to read size[2]"); fclose(fp); return 1; } this->SetDataExtent(0, size[0] - 1, 0, size[1] - 1, 0, size[2] - 1); // Skip Over bits_per_voxel Field */ if (fscanf(fp, "%d", &temp) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to skip over bits per pixel"); fclose(fp); return 1; } if (fscanf(fp, "%lf", f) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to spacing[0]"); fclose(fp); return 1; } if (fscanf(fp, "%lf", f + 1) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to spacing[1]"); fclose(fp); return 1; } if (fscanf(fp, "%lf", f + 2) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to spacing[2]"); fclose(fp); return 1; } this->SetDataSpacing(f); // Skip Over unit_type, data_origin, and data_modification if (fscanf(fp, "%d", &temp) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to skip over unit type"); fclose(fp); return 1; } if (fscanf(fp, "%d", &temp) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to skip over data origin"); fclose(fp); return 1; } if (fscanf(fp, "%d", &temp) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to skip over data modification"); fclose(fp); return 1; } this->SetDataScalarType(VTK_UNSIGNED_CHAR); this->SetNumberOfScalarComponents(1); fclose(fp); return this->Superclass::RequestInformation(request, inputVector, outputVector); } // Reads an SLC file and creates a vtkStructuredPoints dataset. void vtkSLCReader::ExecuteDataWithInformation( vtkDataObject* output_do, vtkInformation* vtkNotUsed(outInfo)) { vtkImageData* output = vtkImageData::SafeDownCast(output_do); FILE* fp; int temp; int data_compression; int plane_size; double f[3]; int size[3]; int magic_num; int z_counter; int icon_width, icon_height; int compressed_size; unsigned char* icon_ptr; unsigned char* compressed_ptr; unsigned char* scan_ptr = nullptr; this->Error = 1; if (!this->FileName) { vtkErrorMacro(<< "A FileName must be specified."); return; } // Initialize if ((fp = vtksys::SystemTools::Fopen(this->FileName, "rb")) == nullptr) { vtkErrorMacro(<< "File " << this->FileName << " not found"); return; } if (fscanf(fp, "%d", &magic_num) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to read magic number"); fclose(fp); return; } if (magic_num != 11111) { vtkErrorMacro(<< "SLC magic number is not correct"); fclose(fp); return; } f[0] = f[1] = f[2] = 0.0; output->SetOrigin(f); if (fscanf(fp, "%d", size) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed read size[0]"); fclose(fp); return; } if (fscanf(fp, "%d", size + 1) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed read size[1]"); fclose(fp); return; } if (fscanf(fp, "%d", size + 2) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed read size[2]"); fclose(fp); return; } output->SetDimensions(size); output->AllocateScalars(VTK_UNSIGNED_CHAR, 1); output->GetPointData()->GetScalars()->SetName("SLCImage"); // Skip Over bits_per_voxel Field */ if (fscanf(fp, "%d", &temp) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to skip over bits per voxel"); fclose(fp); return; } if (fscanf(fp, "%lf", f) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed read spacing[0]"); fclose(fp); return; } if (fscanf(fp, "%lf", f + 1) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed read spacing[1]"); fclose(fp); return; } if (fscanf(fp, "%lf", f + 2) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed read spacing[2]"); fclose(fp); return; } output->SetSpacing(f); // Skip Over unit_type, data_origin, and data_modification if (fscanf(fp, "%d", &temp) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to skip over unit type"); fclose(fp); return; } if (fscanf(fp, "%d", &temp) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to skip over data origin"); fclose(fp); return; } if (fscanf(fp, "%d", &temp) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to skip over data modification"); fclose(fp); return; } if (fscanf(fp, "%d\n", &data_compression) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to read data compression"); fclose(fp); return; } plane_size = size[0] * size[1]; #ifndef NDEBUG int volume_size = plane_size * size[2]; #endif // Skip Over Icon if (fscanf(fp, "%d %d X", &icon_width, &icon_height) != 2) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to skip over icon"); fclose(fp); return; } icon_ptr = new unsigned char[(icon_width * icon_height)]; if (fread(icon_ptr, (icon_width * icon_height), 1, fp) != 1) { vtkErrorMacro( "SLCReader error reading file: " << this->FileName << " Premature EOF while reading icon."); delete[] icon_ptr; fclose(fp); return; } if (fread(icon_ptr, (icon_width * icon_height), 1, fp) != 1) { vtkErrorMacro( "SLCReader error reading file: " << this->FileName << " Premature EOF while reading icon."); delete[] icon_ptr; fclose(fp); return; } if (fread(icon_ptr, (icon_width * icon_height), 1, fp) != 1) { } delete[] icon_ptr; // Read In Data Plane By Plane for (z_counter = 0; z_counter < size[2]; z_counter++) { if (!(z_counter % 10) && !z_counter) { this->UpdateProgress((float)z_counter / size[2]); } // Read a single plane into temp memory switch (data_compression) { case 0: if (!scan_ptr) { scan_ptr = new unsigned char[plane_size]; } if (fread(scan_ptr, 1, plane_size, fp) != (unsigned int)plane_size) { vtkErrorMacro(<< "Unable to read slice " << z_counter << " from SLC File"); fclose(fp); return; } break; case 1: delete[] scan_ptr; if (fscanf(fp, "%d X", &compressed_size) != 1) { vtkErrorMacro(<< "Error reading file: " << this->FileName << "Failed to read compressed size"); fclose(fp); return; } compressed_ptr = new unsigned char[compressed_size]; if (fread(compressed_ptr, 1, compressed_size, fp) != (unsigned int)compressed_size) { vtkErrorMacro(<< "Unable to read compressed slice " << z_counter << " from SLC File"); delete[] compressed_ptr; fclose(fp); return; } scan_ptr = this->Decode8BitData(compressed_ptr, plane_size); delete[] compressed_ptr; break; default: vtkErrorMacro(<< "Unknown SLC compression type: " << data_compression); fclose(fp); return; } void* outputSlice = output->GetScalarPointer(0, 0, z_counter); if (outputSlice && scan_ptr) { memcpy(outputSlice, scan_ptr, plane_size); } } delete[] scan_ptr; vtkDebugMacro(<< "Read " << volume_size << " points"); fclose(fp); this->Error = 0; } int vtkSLCReader::CanReadFile(const char* fname) { FILE* fp; int magic_num = 0; if ((fp = vtksys::SystemTools::Fopen(fname, "rb")) == nullptr) { return 0; } if (fscanf(fp, "%d", &magic_num) != 1) { fclose(fp); return 0; } if (magic_num != 11111) { fclose(fp); return 0; } fclose(fp); return 3; } void vtkSLCReader::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Error: " << this->Error << "\n"; os << indent << "File Name: " << (this->FileName ? this->FileName : "(none)") << "\n"; }