37 #include <gdcmReader.h> 38 #include <gdcmWriter.h> 39 #include <gdcmAttribute.h> 40 #include <gdcmImageReader.h> 41 #include <gdcmImageWriter.h> 42 #include <gdcmImage.h> 43 #include <gdcmPhotometricInterpretation.h> 44 #include <gdcmImage.h> 45 #include <gdcmImageWriter.h> 52 static void to8bits(
int bits_used,
void* ptr,
int px_count,
bool reverse)
54 unsigned char* px = (
unsigned char*)ptr;
57 unsigned int max1 = (1<<bits_used)-1;
58 unsigned int max2 = 0xFF;
59 for(
int i=0; i<px_count; ++i)
61 px[i] = 0xFF - (
unsigned char)( (
float)px[i]/max1*max2 );
63 px[i] = (
unsigned char)( (
float)px[i]/max1*max2 );
65 static void to16bits(
int bits_used,
void* ptr,
int px_count,
bool reverse)
67 unsigned short* px = (
unsigned short*)ptr;
71 unsigned int max1 = (1<<bits_used)-1;
72 unsigned int max2 = 0xFFFF;
73 for(
int i=0; i<px_count; ++i)
76 px[i] = 0xFFFF - (
unsigned short)( (
float)px[i]/max1*max2 );
78 px[i] = (
unsigned short)( (
float)px[i]/max1*max2 );
81 static void to32bits(
int bits_used,
void* ptr,
int px_count,
bool reverse)
83 unsigned int* px = (
unsigned int*)ptr;
86 unsigned int max1 = (1<<bits_used)-1;
87 unsigned int max2 = 0xFFFFFFFF;
88 for(
int i=0; i<px_count; ++i)
90 px[i] = 0xFFFFFFFF - (
unsigned int)( (
float)px[i]/max1*max2 );
92 px[i] = (
unsigned int)( (
float)px[i]/max1*max2 );
110 gdcm::ImageReader reader;
118 const int bufsize = 128*1024;
119 char buffer[bufsize];
121 std::stringstream strstr;
122 while( (count=vfile->
read(buffer, bufsize)) )
123 strstr.write(buffer,(
int)count);
124 std::istream* istr = &strstr;
125 reader.SetStream( *istr );
128 std::cerr <<
"Could not read: " << vfile->
path().
toStdString() << std::endl;
133 gdcm::File &file = reader.GetFile();
134 const gdcm::Image &image = reader.GetImage();
137 printf(
"GDCM --- --- --- --- ---\n");
138 image.Print(std::cout);
141 unsigned int ndim = image.GetNumberOfDimensions();
142 const unsigned int *dims = image.GetDimensions();
143 gdcm::PixelFormat pf = image.GetPixelFormat();
144 const gdcm::PhotometricInterpretation &pi = image.GetPhotometricInterpretation();
157 tags->
set(
"Origin") =
Say(
"%n %n %n") << image.GetOrigin()[0] << image.GetOrigin()[1] << image.GetOrigin()[2];
158 tags->
set(
"Spacing") =
Say(
"%n %n %n") << image.GetSpacing()[0] << image.GetSpacing()[1] << image.GetSpacing()[2];
159 tags->
set(
"Intercept") =
Say(
"%n") << image.GetIntercept();
160 tags->
set(
"Slope") =
Say(
"%n") << image.GetSlope();
161 tags->
set(
"DirectionCosines") =
Say(
"%n %n %n %n %n %n")
162 << image.GetDirectionCosines()[0] << image.GetDirectionCosines()[1] << image.GetDirectionCosines()[2]
163 << image.GetDirectionCosines()[3] << image.GetDirectionCosines()[4] << image.GetDirectionCosines()[5];
164 tags->
set(
"BitsStored") =
Say(
"%n") << pf.GetBitsStored();
166 gdcm::DataSet& ds = file.GetDataSet();
169 gdcm::Attribute<0x28,0x1050> win_center;
170 const gdcm::DataElement& de = ds.GetDataElement( win_center.GetTag() );
173 win_center.SetFromDataElement( ds.GetDataElement( win_center.GetTag() ) );
174 tags->
set(
"WindowCenter") =
Say(
"%n") << win_center.GetValue();
179 gdcm::Attribute<0x28,0x1051> win_width;
180 const gdcm::DataElement& de = ds.GetDataElement( win_width.GetTag() );
183 win_width.SetFromDataElement( ds.GetDataElement( win_width.GetTag() ) );
184 tags->
set(
"WindowWidth") =
Say(
"%n") << win_width.GetValue();
189 gdcm::Attribute<0x28,0x1052> rescale_intercept;
190 const gdcm::DataElement& de = ds.GetDataElement( rescale_intercept.GetTag() );
193 rescale_intercept.SetFromDataElement( ds.GetDataElement( rescale_intercept.GetTag() ) );
194 tags->
set(
"RescaleIntercept") =
Say(
"%n") << rescale_intercept.GetValue();
197 tags->
set(
"RescaleIntercept") =
Say(
"%n") << 0;
201 gdcm::Attribute<0x28,0x1053> rescale_slope;
202 const gdcm::DataElement& de = ds.GetDataElement( rescale_slope.GetTag() );
205 rescale_slope.SetFromDataElement( ds.GetDataElement( rescale_slope.GetTag() ) );
206 tags->
set(
"RescaleSlope") =
Say(
"%n") << rescale_slope.GetValue();
209 tags->
set(
"RescaleIRescaleSlopentercept") =
Say(
"%n") << 1;
213 printf(
"TAGS --- --- --- --- ---\n");
228 if (pf.GetSamplesPerPixel() == 1 && pi == gdcm::PhotometricInterpretation::PALETTE_COLOR)
230 if (pf.GetBitsStored() <= 8)
233 image.GetBuffer((
char*)img->
pixels());
235 const gdcm::LookupTable& lut = image.GetLUT();
236 std::auto_ptr<char> rgba(
new char[(1<<lut.GetBitSample())*4] );
237 lut.GetBufferAsRGBA((
unsigned char*)rgba.get());
238 for(
int i=w*h; i--; )
240 int idx = img->
pixels()[i];
241 img->
pixels()[i*4+0] = rgba.get()[idx*4+0];
242 img->
pixels()[i*4+1] = rgba.get()[idx*4+1];
243 img->
pixels()[i*4+2] = rgba.get()[idx*4+2];
244 img->
pixels()[i*4+3] = rgba.get()[idx*4+3];
248 if (pf.GetBitsStored() <= 16)
251 image.GetBuffer((
char*)img->
pixels());
253 const gdcm::LookupTable& lut = image.GetLUT();
254 std::auto_ptr<char> rgba(
new char[(1<<lut.GetBitSample())*4] );
255 lut.GetBufferAsRGBA((
unsigned char*)rgba.get());
256 for(
int i=w*h; i--; )
258 int idx = ((
unsigned short*)img->
pixels())[i];
259 img->
pixels()[i*4+0] = rgba.get()[idx*4+0];
260 img->
pixels()[i*4+1] = rgba.get()[idx*4+1];
261 img->
pixels()[i*4+2] = rgba.get()[idx*4+2];
262 img->
pixels()[i*4+3] = rgba.get()[idx*4+3];
267 if (pf.GetSamplesPerPixel() == 1 && (pi == gdcm::PhotometricInterpretation::MONOCHROME2 || pi == gdcm::PhotometricInterpretation::MONOCHROME1))
269 if (pf.GetBitsStored() <= 8)
272 image.GetBuffer((
char*)img->
pixels());
273 if (pi == gdcm::PhotometricInterpretation::MONOCHROME1)
274 to8bits(pf.GetBitsStored(), img->
pixels(), w*h,
true);
276 to8bits(pf.GetBitsStored(), img->
pixels(), w*h,
false);
279 if (pf.GetBitsStored() <= 16)
282 image.GetBuffer((
char*)img->
pixels());
283 if (pi == gdcm::PhotometricInterpretation::MONOCHROME1)
284 to16bits(pf.GetBitsStored(), img->
pixels(), w*h,
true);
286 to16bits(pf.GetBitsStored(), img->
pixels(), w*h,
false);
289 if (pf.GetBitsStored() <= 32)
292 image.GetBuffer((
char*)img->
pixels());
293 if (pi == gdcm::PhotometricInterpretation::MONOCHROME1)
294 to32bits(pf.GetBitsStored(), img->
pixels(), w*h,
true);
296 to32bits(pf.GetBitsStored(), img->
pixels(), w*h,
false);
300 if (pf.GetSamplesPerPixel() == 3)
302 if (pf.GetBitsStored() <= 8)
305 image.GetBuffer((
char*)img->
pixels());
306 if (image.GetPlanarConfiguration())
308 int slice_pix_count = w*h/d;
309 std::auto_ptr<char> px (
new char[slice_pix_count*3] );
310 for(
int slice=0; slice<d; ++slice)
312 char* red = (
char* )img->
pixels() + slice*slice_pix_count*3 + 0;
313 char* green = (
char* )img->
pixels() + slice*slice_pix_count*3 + slice_pix_count;
314 char* blue = (
char* )img->
pixels() + slice*slice_pix_count*3 + slice_pix_count*2;
315 for(
int i=0; i<slice_pix_count*3; i+=3, ++red, ++green, ++blue)
317 px.get()[i+0] = *red;
318 px.get()[i+1] = *green;
319 px.get()[i+2] = *blue;
326 if (pf.GetBitsStored() <= 16)
329 image.GetBuffer((
char*)img->
pixels());
330 if (image.GetPlanarConfiguration())
332 int slice_pix_count = w*h/d;
333 std::auto_ptr<short> px (
new short[slice_pix_count*3] );
334 for(
int slice=0; slice<d; ++slice)
336 short* red = (
short* )img->
pixels() + slice*slice_pix_count*3 + 0;
337 short* green = (
short* )img->
pixels() + slice*slice_pix_count*3 + slice_pix_count;
338 short* blue = (
short* )img->
pixels() + slice*slice_pix_count*3 + slice_pix_count*2;
339 for(
int i=0; i<slice_pix_count*3; i+=3, ++red, ++green, ++blue)
341 px.get()[i+0] = *red;
342 px.get()[i+1] = *green;
343 px.get()[i+2] = *blue;
351 vl::Log::error(
"DICOM format not supported: SamplesPerPixel = 3, BitsStored > 16.\n\n");
352 image.Print(std::cout);
360 image.Print(std::cout);
376 char signature[] = {
'D',
'I',
'C',
'M' };
377 char buf[] = { 0, 0, 0, 0 };
379 bool ok = memcmp(buf,signature,4) == 0;
401 unsigned short bps = 0;
412 unsigned short spp = 0;
434 gdcm::SmartPointer<gdcm::Image> im =
new gdcm::Image;
435 im->SetNumberOfDimensions( img->
dimension() );
438 im->SetDimension( i, dims[i] );
440 im->GetPixelFormat().SetScalarType(bps==8?gdcm::PixelFormat::INT8:gdcm::PixelFormat::INT16);
441 im->GetPixelFormat().SetBitsAllocated(bps*8);
442 im->GetPixelFormat().SetBitsStored(bps*8);
443 im->GetPixelFormat().SetHighBit(bps*8-1);
444 im->GetPixelFormat().SetSamplesPerPixel(spp);
445 gdcm::PhotometricInterpretation pi = spp==1?gdcm::PhotometricInterpretation::MONOCHROME2:gdcm::PhotometricInterpretation::RGB;
446 im->SetPhotometricInterpretation(pi);
449 unsigned long len = im->GetBufferLength();
461 gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0,0x0010) );
462 pixeldata.SetByteValue( (
const char*)img->
pixels(), len );
463 im->SetDataElement( pixeldata );
467 std::ostringstream ostr;
475 int bcount = (int)fout->
write(ostr.str().c_str(), ostr.str().length());
477 if( bcount != (
int)ostr.str().length() )
long long read(void *buffer, long long byte_count)
Reads byte_count bytes from a file. Returns the number of bytes actually read.
VLCORE_EXPORT FileSystem * defFileSystem()
Returns the default FileSystem used by VisualizationLibrary.
An abstract class representing a file.
A simple String formatting class.
const unsigned char * pixels() const
Raw pointer to pixels.
void setObjectName(const char *name)
The name of the object, by default set to the object's class name in debug builds.
VLCORE_EXPORT ref< Image > loadDICOM(VirtualFile *file)
Loads a DICOM file.
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
virtual ref< VirtualFile > locateFile(const String &full_path, const String &alternate_path=String()) const
Looks for a VirtualFile on the disk and in the currently active FileSystem.
int requiredMemory() const
Returns the number of bytes requested to store the image.
virtual void close()=0
Closes the file.
const String & path() const
Returns the path of the file.
VLCORE_EXPORT bool isDICOM(VirtualFile *file)
Checks if the given file is a DICOM file.
Visualization Library main namespace.
VLCORE_EXPORT bool saveDICOM(const Image *src, const String &path)
Writes a DICOM file.
EImageDimension dimension() const
Implements the OpenGL Shading Language convenience functions for scalar and vector operations...
long long write(const void *buffer, long long byte_count)
Writes byte_count bytes to a file. Returns the number of bytes actually written.
virtual bool open(EOpenMode mode)=0
Opens the file in the specified mode.
bool seekSet(long long offset)
Changes the current read/write position of a file.
void setTags(KeyValues *tags)
A set of key/value couples that can be used to attach extra information to an image like DICOM inform...
ref< Image > convertFormat(EImageFormat new_format) const
Converts the format() of an image.
A VirtualFile that operates on regular disk files.
Implements a generic 1d, 2d, 3d and cubemap image that can have mipmaps.
The ref<> class is used to reference-count an Object.
void allocate2D(int x, int y, int bytealign, EImageFormat format, EImageType type)
std::string toStdString() const
Returns a UTF8 encoded std::string.
String & set(const String &key)
A set of key/value pairs usually used to associate generic information, tags, attributes etc...
EImageFormat format() const