/* * Copyright (c) ICG. All rights reserved. * See copyright.txt for more information. * * Institute for Computer Graphics and Vision * Graz, University of Technology / Austria * * * This software is distributed WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the above copyright notices for more information. * * * Project : MIPItkProjects * Module : CommonItkUtilities * Class : $RCSfile: VolumeIOWrapper.txx,v $ * Language : C++ * Description : * * Author : Martin Urschler * EMail : urschler@icg.tu-graz.ac.at * Date : $Date: 2007-04-23 11:38:56 $ * Version : $Revision: 1.21 $ * Full Id : $Id: VolumeIOWrapper.txx,v 1.21 2007-04-23 11:38:56 urschler Exp $ * */ #ifndef __VOLUME_IO_WRAPPER_TXX__ #define __VOLUME_IO_WRAPPER_TXX__ #include "SmallUtilityMethods.h" #include "itkMersenneTwisterRandomVariateGenerator.h" #include "itkImageFileReader.h" #include "itkImageFileWriter.h" #include "itkCastImageFilter.h" #include "itkRescaleIntensityImageFilter.h" #include "itkShiftScaleImageFilter.h" #include "itkImageSliceConstIteratorWithIndex.h" #include "itkImageSeriesReader.h" #include "itkImageSeriesWriter.h" #include "itkGDCMImageIO.h" #include "itkGDCMSeriesFileNames.h" #include void printMetaDataDictionary( const itk::MetaDataDictionary& dictionary ) { std::cout << "output of meta data dictionary" << std::endl; typedef itk::MetaDataDictionary DictionaryType; typedef itk::MetaDataObject< std::string > MetaDataStringType; DictionaryType::ConstIterator itr = dictionary.Begin(); DictionaryType::ConstIterator end = dictionary.End(); while( itr != end ) { itk::MetaDataObjectBase::Pointer entry = itr->second; MetaDataStringType::Pointer entryvalue = dynamic_cast( entry.GetPointer() ) ; if( entryvalue ) { std::string tagkey = itr->first; std::string labelId; std::string tagvalue = entryvalue->GetMetaDataObjectValue(); std::cout << "(" << tagkey << ") " << "Unknown"; std::cout << " = " << tagvalue.c_str() << std::endl; } ++itr; } } template< typename TImageType > typename VolumeIOWrapper::TImageTypePointer VolumeIOWrapper::readITKDicomSeries( const std::string& input_directory_name, typename VolumeIOWrapper::TImageSeriesReaderPointerType& series_reader_ret_val, int whichSeries ) { typedef itk::ImageSeriesReader< TImageType > SeriesReaderType; typedef itk::GDCMImageIO ImageIOType; ImageIOType::Pointer gdcmIO = ImageIOType::New(); itk::GDCMSeriesFileNames::Pointer nameGenerator = itk::GDCMSeriesFileNames::New(); nameGenerator->SetInputDirectory( input_directory_name.c_str() ); //nameGenerator->Print(std::cout); //const itk::SerieUIDContainer& seriesUIDs = series_files->GetSeriesUIDs(); // debug //std::vector actualSeriesFileNames = // allSeriesFileNames->GetInputFileNames(); //std::vector series_names = // series_files->GetFileNames( seriesUIDs[whichSeries] ); series_reader_ret_val = SeriesReaderType::New(); //series_reader_ret_val->ReverseOrderOn(); const typename SeriesReaderType::FileNamesContainer& filenames = nameGenerator->GetInputFileNames(); for (int i=0; iSetFileNames( filenames ); series_reader_ret_val->SetImageIO( gdcmIO ); std::string message = std::string("Reading dicom image series from ") + input_directory_name; ITK_EXCEPTION_CHECKED( message, series_reader_ret_val->Update(), 0 ); std::cout << "Have read " << filenames.size() << " images." << std::endl; //printMetaDataDictionary( gdcmIO->GetMetaDataDictionary() ); return series_reader_ret_val->GetOutput(); } template< typename TImageType > bool VolumeIOWrapper::writeITKDicomSeries( const typename VolumeIOWrapper::TImageTypePointer& image, const std::string& input_directory_name, const std::string& output_directory_name, const typename VolumeIOWrapper::TImageSeriesReaderPointerType& series_reader ) { itksys::SystemTools::MakeDirectory( output_directory_name.c_str() ); typename TImageType::PixelType minimum_voxel_value = SmallUtilityMethods::getMinimumVoxelValue( image ); std::cout << "minimum voxel value: " << minimum_voxel_value << std::endl; //typename TImageType::PixelType maximum_voxel_value = // SmallUtilityMethods::getMaximumVoxelValue( image ); //std::cout << "maximum voxel value: " << maximum_voxel_value << std::endl; typename TImageType::Pointer prepared_image; if (minimum_voxel_value < 0) { // shift intensities typedef itk::ShiftScaleImageFilter< TImageType, TImageType > ShiftFilterType; typename ShiftFilterType::Pointer filter = ShiftFilterType::New(); filter->SetInput( image ); //filter->SetShift( - minimum_voxel_value ); filter->SetShift( 1024 ); ITK_EXCEPTION_CHECKED( "Shifting image intensities.", filter->Update(), false ); prepared_image = filter->GetOutput(); } else { prepared_image = image; } typedef itk::Image Image2DType; typedef itk::ImageSeriesWriter< TImageType, Image2DType > SeriesWriterType; typedef itk::GDCMImageIO ImageIOType; typedef itk::GDCMSeriesFileNames SeriesFileNames; ImageIOType::Pointer gdcmIO = ImageIOType::New(); typename SeriesWriterType::Pointer swriter = SeriesWriterType::New(); swriter->SetInput( prepared_image ); swriter->SetImageIO( gdcmIO ); SeriesFileNames::Pointer series_files = SeriesFileNames::New(); series_files->SetInputDirectory( input_directory_name.c_str() ); series_files->GetInputFileNames(); // only called to be up to date series_files->SetOutputDirectory( output_directory_name.c_str() ); typename SeriesWriterType::FileNamesContainer filenames = series_files->GetOutputFileNames(); std::reverse( filenames.begin(), filenames.end() ); swriter->SetFileNames( filenames ); swriter->SetMetaDataDictionaryArray( series_reader->GetMetaDataDictionaryArray() ); //printMetaDataDictionary( // series_reader->GetMetaDataDictionaryArray() ); std::string message = std::string("Writing dicom image series to ") + output_directory_name; ITK_EXCEPTION_CHECKED( message, swriter->Update(), false ); return true; } template< typename TImageType > typename VolumeIOWrapper::TImageTypePointer VolumeIOWrapper::readITKVolume( const std::string& filename, const std::string& extension ) { std::string read_filename = constructFinalFilename( filename, extension ); typedef itk::ImageFileReader< TImageType > ReaderType; typename ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName( read_filename.c_str() ); std::string message = std::string("Reading volume ") + read_filename; ITK_EXCEPTION_CHECKED( message, reader->Update(), 0 ); return reader->GetOutput(); } template< typename TImageType > bool VolumeIOWrapper::writeITKVolume16Bit( const typename VolumeIOWrapper::TImageTypePointer& image, const std::string& base_filename, const std::string& filename_extension) { std::string write_filename = constructFinalFilename( base_filename, filename_extension ); typedef Int16ImageType OutputImageType; typedef itk::CastImageFilter< TImageType, OutputImageType > CastImageFilterType; typename CastImageFilterType::Pointer caster = CastImageFilterType::New(); caster->SetInput( image ); typedef itk::ImageFileWriter< OutputImageType > WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetFileName( write_filename.c_str() ); writer->SetInput( caster->GetOutput() ); try { std::cout << "writing image " << write_filename.c_str() << std::endl; writer->Update(); } catch ( itk::ExceptionObject & err ) { std::cout << "ExceptionObject caught !" << std::endl; std::cout << err << std::endl; return false; } // doesn't work yet //zipTheDataFile( write_filename ); return true; } template< typename TImageType > bool VolumeIOWrapper::writeITKVolume8Bit( const typename VolumeIOWrapper::TImageTypePointer& image, const std::string& base_filename, const std::string& filename_extension, bool cast_to_values_betw_0_255 ) { std::string write_filename = constructFinalFilename( base_filename, filename_extension ); typedef UInt8ImageType OutputImageType; typedef itk::ImageFileWriter< OutputImageType > WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetFileName( write_filename.c_str() ); if (cast_to_values_betw_0_255 == true) { typedef itk::RescaleIntensityImageFilter< TImageType, OutputImageType > CastImageFilterType; typename CastImageFilterType::Pointer caster = CastImageFilterType::New(); caster->SetOutputMinimum( 0 ); caster->SetOutputMaximum( 255 ); // pipeline caster->SetInput( image ); writer->SetInput( caster->GetOutput() ); std::string message = std::string("Writing Image ") + write_filename + std::string( " as 8bit image which has been cast to lie between 0 and 255."); ITK_EXCEPTION_CHECKED( message, writer->Update(), false ); } else { typedef itk::CastImageFilter< TImageType, OutputImageType > CastImageFilterType; typename CastImageFilterType::Pointer caster = CastImageFilterType::New(); // sanity checks typename TImageType::PixelType min_value = SmallUtilityMethods::getMinimumVoxelValue( image ); typename TImageType::PixelType max_value = SmallUtilityMethods::getMaximumVoxelValue( image ); assert(min_value >= 0); assert(max_value <= 255); // pipeline caster->SetInput( image ); writer->SetInput( caster->GetOutput() ); std::string message = std::string("Writing Image ") + write_filename + std::string(" as 8bit image with the unmodified grey values."); ITK_EXCEPTION_CHECKED( message, writer->Update(), false ); } // doesn't work yet //zipTheDataFile( write_filename ); return true; } #ifndef VCL_WIN32 #include template< typename TImageType > void VolumeIOWrapper::zipTheDataFile( const std::string& filename ) { pid_t pid; int status = 0; pid = fork(); if (pid == 0) // child process { std::cout << "executing: gzip " << filename.c_str() << std::endl; execl( "/bin/gzip", filename.c_str() ); } else // parent process { wait(); // wait for successful completion of newly executed application } } #else template< typename TImageType > void VolumeIOWrapper::zipTheDataFile( const std::string& filename ) { // do nothing for now std::cout << "FIXXXME: spawning external process to zip data file not yet" << "implemented for Windows!" << std::endl; } #endif // some private local functions to support the dicom writer template< typename TImageType > void VolumeIOWrapper::convertShortTo2Bytes( const MY_UINT16& word_val, MY_UINT8& byte0, MY_UINT8& byte1, bool little_endian ) { const MY_UINT16 extract_lo = 0x00ff; const MY_UINT16 extract_hi = 0xff00; if (little_endian) { byte0 = static_cast< MY_UINT8 > ( word_val & extract_lo ); byte1 = static_cast< MY_UINT8 > ( (word_val & extract_hi) >> 8 ); } else { byte1 = static_cast< MY_UINT8 > ( word_val & extract_lo ); byte0 = static_cast< MY_UINT8 > ( (word_val & extract_hi) >> 8 ); } } template< typename TImageType > void VolumeIOWrapper::convertIntTo4Bytes( const MY_UINT32& int_val, MY_UINT8& byte0, MY_UINT8& byte1, MY_UINT8& byte2, MY_UINT8& byte3, bool little_endian ) { const MY_UINT32 extract_low = 0x000000ff; const MY_UINT32 extract_mid1 = 0x0000ff00; const MY_UINT32 extract_mid2 = 0x00ff0000; const MY_UINT32 extract_high = 0xff000000; if (little_endian) { byte0 = static_cast< MY_UINT8 > ( (int_val & extract_low ) ); byte1 = static_cast< MY_UINT8 > ( (int_val & extract_mid1) >> 8 ); byte2 = static_cast< MY_UINT8 > ( (int_val & extract_mid2) >> 16 ); byte3 = static_cast< MY_UINT8 > ( (int_val & extract_high) >> 24 ); } else { byte3 = static_cast< MY_UINT8 > ( (int_val & extract_low ) ); byte2 = static_cast< MY_UINT8 > ( (int_val & extract_mid1) >> 8 ); byte1 = static_cast< MY_UINT8 > ( (int_val & extract_mid2) >> 16 ); byte0 = static_cast< MY_UINT8 > ( (int_val & extract_high) >> 24 ); } } template< typename TImageType > bool VolumeIOWrapper::writeDicomValue32( std::ostream& stream, MY_UINT16 group_nr, MY_UINT16 tag_nr, MY_UINT8 cS_1, MY_UINT8 cS_2, MY_UINT32 val, bool little_endian ) { MY_UINT8 byte0 = 0x00; MY_UINT8 byte1 = 0x00; convertShortTo2Bytes( group_nr, byte0, byte1, little_endian ); stream << byte0 << byte1; convertShortTo2Bytes( tag_nr, byte0, byte1, little_endian ); stream << byte0 << byte1; stream << cS_1 << cS_2; MY_UINT16 len = 4; convertShortTo2Bytes( len, byte0, byte1, little_endian ); stream << byte0 << byte1; MY_UINT8 byte2 = 0x00; MY_UINT8 byte3 = 0x00; convertIntTo4Bytes( val, byte0, byte1, byte2, byte3, little_endian ); stream << byte0 << byte1 << byte2 << byte3; return true; } template< typename TImageType > bool VolumeIOWrapper::writeDicomValue16( std::ostream& stream, MY_UINT16 group_nr, MY_UINT16 tag_nr, MY_UINT8 cS_1, MY_UINT8 cS_2, MY_UINT16 val, bool little_endian ) { MY_UINT8 byte0 = 0x00; MY_UINT8 byte1 = 0x00; convertShortTo2Bytes( group_nr, byte0, byte1, little_endian ); stream << byte0 << byte1; convertShortTo2Bytes( tag_nr, byte0, byte1, little_endian ); stream << byte0 << byte1; stream << cS_1 << cS_2; MY_UINT16 len = 2; convertShortTo2Bytes( len, byte0, byte1, little_endian ); stream << byte0 << byte1; convertShortTo2Bytes( val, byte0, byte1, little_endian ); stream << byte0 << byte1; return true; } template< typename TImageType > bool VolumeIOWrapper::writeDicomString( std::ostream& stream, MY_UINT16 group_nr, MY_UINT16 tag_nr, MY_UINT8 cS_1, MY_UINT8 cS_2, const char* string, bool little_endian) { bool append_space = false; MY_UINT16 len = strlen(string); MY_UINT16 corrected_len = (((len+1)>>1)<<1); // round up to full 2 if (corrected_len != len) append_space = true; MY_UINT8 byte0 = 0x00; MY_UINT8 byte1 = 0x00; convertShortTo2Bytes( group_nr, byte0, byte1, little_endian ); stream << byte0 << byte1; convertShortTo2Bytes( tag_nr, byte0, byte1, little_endian ); stream << byte0 << byte1; stream << cS_1 << cS_2; convertShortTo2Bytes( corrected_len, byte0, byte1, little_endian ); stream << byte0 << byte1; for (int i=0; i void VolumeIOWrapper::writeDicomOBMetaInfoValue( std::ostream& stream, bool little_endian ) { MY_UINT8 byte0 = 0x00; MY_UINT8 byte1 = 0x00; MY_UINT8 byte2 = 0x00; MY_UINT8 byte3 = 0x00; convertShortTo2Bytes( static_cast( 0x0002 ), byte0, byte1, little_endian ); stream << byte0 << byte1; convertShortTo2Bytes( static_cast( 0x0001 ), byte0, byte1, little_endian ); stream << byte0 << byte1; stream << 'O' << 'B'; convertShortTo2Bytes( static_cast( 0 ), byte0, byte1, little_endian ); stream << byte0 << byte1; convertIntTo4Bytes( static_cast( 2 ), byte0, byte1, byte2, byte3, little_endian ); stream << byte0 << byte1 << byte2 << byte3; convertShortTo2Bytes( static_cast( 256 ), byte0, byte1, little_endian ); stream << byte0 << byte1; } template< typename TImageType > bool VolumeIOWrapper::writeITKVolumeAsDicomFiles( const typename VolumeIOWrapper::TImageTypePointer& image, const std::string& directory_filename ) { const bool little_endian = true; typename TImageType::SpacingType spacing = image->GetSpacing(); typedef itk::ImageSliceConstIteratorWithIndex IteratorType; IteratorType img_it = IteratorType ( image, image->GetLargestPossibleRegion() ); img_it.SetFirstDirection(0); img_it.SetSecondDirection(1); img_it.GoToBegin(); const int wYear = 1900; const int wMonth = 1; const int wDay = 1; const int wHour = 1; const int wMinute = 1; const int wSecond = 1; const int wMilliseconds =1; char date[15]; sprintf(date, "%4d%02d%02d", wYear, wMonth, wDay); typename TImageType::SizeType img_size = image->GetLargestPossibleRegion().GetSize(); int the_Width = img_size[0]; int the_Height = img_size[1]; int the_Depth = img_size[2]; char string_buffer[1000]; MY_UINT8 null = 0; const char dicm_string[] = "DICM"; const MY_UINT32 length_of_ob_meta_info_header = 14; const char media_storage_sop_class_uid[] = "1.2.840.10008.5.1.4.1.1.2"; const MY_UINT32 length_of_02_02 = 8 + (((strlen(media_storage_sop_class_uid)+1)>>1)<<1); const char transfer_syntax_uid[] = "1.2.840.10008.1.2.1"; const MY_UINT32 length_of_02_10 = 8 + (((strlen(transfer_syntax_uid)+1)>>1)<<1); const char implementation_class_uid[] = "1.3.12.2.1107.5.9.20000101"; const MY_UINT32 length_of_02_12 = 8 + (((strlen(implementation_class_uid)+1)>>1)<<1); const char implementation_version_name[] = "SIEMENS_SWFVB10A"; const MY_UINT32 length_of_02_13 = 8 + (((strlen(implementation_version_name)+1)>>1)<<1); const MY_UINT32 meta_info_header_length_of_static_parts = length_of_ob_meta_info_header + length_of_02_02 + length_of_02_10 + length_of_02_12 + length_of_02_13; for (int z=0; z>1)<<1); //std::cout << "length_of_02_02: " << length_of_02_02 << std::endl; //std::cout << "length_of_02_03: " << length_of_02_03 << std::endl; //std::cout << "length_of_02_10: " << length_of_02_10 << std::endl; //std::cout << "length_of_02_12: " << length_of_02_12 << std::endl; //std::cout << "length_of_02_13: " << length_of_02_13 << std::endl; const MY_UINT32 meta_info_header_group_length = meta_info_header_length_of_static_parts + length_of_02_03; writeDicomValue32(the_DiskFile, 0x0002, 0x0000, 'U', 'L', meta_info_header_group_length, little_endian); writeDicomOBMetaInfoValue( the_DiskFile, little_endian ); writeDicomString(the_DiskFile, 0x0002, 0x0002, 'U', 'I', media_storage_sop_class_uid, little_endian); writeDicomString(the_DiskFile, 0x0002, 0x0003, 'U', 'I', string_buffer, little_endian); writeDicomString(the_DiskFile, 0x0002, 0x0010, 'U', 'I', transfer_syntax_uid, little_endian); writeDicomString(the_DiskFile, 0x0002, 0x0012, 'U', 'I', implementation_class_uid, little_endian); writeDicomString(the_DiskFile, 0x0002, 0x0013, 'S', 'H', implementation_version_name, little_endian); writeDicomString(the_DiskFile, 0x0008, 0x0008, 'C', 'S', "AXIAL", little_endian); writeDicomString(the_DiskFile, 0x0008, 0x0016, 'U', 'I', "1.2.840.10008.5.1.4.1.1.2", little_endian); writeDicomString(the_DiskFile, 0x0008, 0x0018, 'U', 'I', string_buffer, little_endian); writeDicomString(the_DiskFile, 0x0008, 0x0020, 'D', 'A', date, little_endian); writeDicomString(the_DiskFile, 0x0008, 0x0022, 'D', 'A', date, little_endian); writeDicomString(the_DiskFile, 0x0008, 0x0023, 'D', 'A', date, little_endian); writeDicomString(the_DiskFile, 0x0008, 0x0030, 'T', 'M', "000000.000000", little_endian); writeDicomString(the_DiskFile, 0x0008, 0x0032, 'T', 'M', "000000.100000", little_endian); writeDicomString(the_DiskFile, 0x0008, 0x0033, 'T', 'M', "000001.000000", little_endian); writeDicomString(the_DiskFile, 0x0008, 0x0050, 'S', 'H', "01", little_endian); writeDicomString(the_DiskFile, 0x0008, 0x0060, 'C', 'S', "CT", little_endian); writeDicomString(the_DiskFile, 0x0008, 0x0070, 'L', 'O', "Siemens", little_endian); writeDicomString(the_DiskFile, 0x0008, 0x0090, 'P', 'N', "", little_endian); writeDicomString(the_DiskFile, 0x0008, 0x103e, 'L', 'O', "3D_IMAGES", little_endian); // *********************************************************************** writeDicomString(the_DiskFile, 0x0010, 0x0010, 'P', 'N', "Patient Name", little_endian); writeDicomString(the_DiskFile, 0x0010, 0x0020, 'L', 'O', "Patient Id", little_endian); writeDicomString(the_DiskFile, 0x0010, 0x0030, 'D', 'A', "Patient Birthday", little_endian); writeDicomString(the_DiskFile, 0x0010, 0x0040, 'C', 'S', "Patient Sex", little_endian); // *********************************************************************** double the_SliceThickness = spacing[2]; sprintf( string_buffer, "%0.7f", the_SliceThickness ); writeDicomString(the_DiskFile, 0x0018, 0x0050, 'D', 'S', string_buffer, little_endian); writeDicomString(the_DiskFile, 0x0018, 0x0060, 'D', 'S', "", little_endian); // KVP writeDicomString(the_DiskFile, 0x0018, 0x5100, 'C', 'S', "HFS ", little_endian); // patient orientation // *********************************************************************** writeDicomString(the_DiskFile, 0x0020, 0x000d, 'U', 'I', "1.3.12.2.1107.5.8.1.12345.PatientId.StudyId.StudyInstanceUID", little_endian); writeDicomString(the_DiskFile, 0x0020, 0x000e, 'U', 'I', "1.3.12.2.1107.5.8.1.12345.PatientId.SeriesId.SeriesInstanceUID", little_endian); writeDicomString(the_DiskFile, 0x0020, 0x0010, 'S', 'H', "StudyId", little_endian); writeDicomString(the_DiskFile, 0x0020, 0x0011, 'I', 'S', "SeriesId", little_endian); writeDicomString(the_DiskFile, 0x0020, 0x0012, 'I', 'S', "", little_endian); // acquisition number sprintf(string_buffer, "%d", z); // instance number writeDicomString(the_DiskFile, 0x0020, 0x0013, 'I', 'S', string_buffer, little_endian); // *********************************************************************** sprintf( string_buffer, "0.000\\ 0.000\\ %0.3f", double(z) * the_SliceThickness ); writeDicomString(the_DiskFile, 0x0020, 0x0032, 'D', 'S', string_buffer, little_endian); writeDicomString(the_DiskFile, 0x0020, 0x0037, 'D', 'S', "1.000\\ 0.000\\ 0.000\\ 0.000\\-1.000\\ 0.000", little_endian); writeDicomString(the_DiskFile, 0x0020, 0x0052, 'U', 'I', "1.3.12.2.1107.5.8.1.12345.PatientId.SeriesInstance", little_endian); writeDicomString(the_DiskFile, 0x0020, 0x1040, 'L', 'O', "", little_endian); // position reference indicator writeDicomValue16(the_DiskFile, 0x0028, 0x0002, 'U', 'S', 1, little_endian); // samples per pixel writeDicomString(the_DiskFile, 0x0028, 0x0004, 'C', 'S', "MONOCHROME2 ", little_endian); // photometric interpretation writeDicomValue16(the_DiskFile, 0x0028, 0x0010, 'U', 'S', the_Width, little_endian); // image width writeDicomValue16(the_DiskFile, 0x0028, 0x0011, 'U', 'S', the_Height, little_endian); // image height sprintf(string_buffer, "%0.7f\\%0.7f", spacing[0], spacing[1]); writeDicomString(the_DiskFile, 0x0028, 0x0030, 'D', 'S', string_buffer, little_endian); // image row and column spacing writeDicomValue16(the_DiskFile, 0x0028, 0x0100, 'U', 'S', 16, little_endian); // bits allocated writeDicomValue16(the_DiskFile, 0x0028, 0x0101, 'U', 'S', 12, little_endian); // bits stored writeDicomValue16(the_DiskFile, 0x0028, 0x0102, 'U', 'S', 11, little_endian); // high bit writeDicomValue16(the_DiskFile, 0x0028, 0x0103, 'U', 'S', 0 , little_endian); // pixel representation writeDicomString(the_DiskFile, 0x0028, 0x1052, 'D', 'S', "-1024", little_endian); // rescale intercept writeDicomString(the_DiskFile, 0x0028, 0x1053, 'D', 'S', "1", little_endian); // rescale slope writeDicomString(the_DiskFile, 0x7fe0, 0x0010, 'O', 'W', "", little_endian); // pixel data { MY_UINT8 byte0 = 0x00; MY_UINT8 byte1 = 0x00; MY_UINT8 byte2 = 0x00; MY_UINT8 byte3 = 0x00; MY_UINT32 data_buffer_size = 2 * the_Width * the_Height; convertIntTo4Bytes( data_buffer_size, byte0, byte1, byte2, byte3, little_endian ); the_DiskFile << byte0 << byte1 << byte2 << byte3; } // now write pixel data while( !img_it.IsAtEndOfSlice()) { while( !img_it.IsAtEndOfLine() ) { signed short signed_voxel_value = static_cast( img_it.Get() ); if (signed_voxel_value < -1024) signed_voxel_value = -1024; if (signed_voxel_value > (32767-1024)) signed_voxel_value = (32767-1024); signed_voxel_value += 1024; // make it positive MY_UINT16 voxel_value = static_cast( signed_voxel_value ); MY_UINT8 byte0 = 0x00; MY_UINT8 byte1 = 0x00; convertShortTo2Bytes( voxel_value, byte0, byte1, little_endian ); the_DiskFile << byte0 << byte1; ++img_it; } img_it.NextLine(); } img_it.NextSlice(); } return true; } #endif