Orfeo Toolbox  3.16
itkTIFFImageIO.cxx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkTIFFImageIO.cxx,v $
5  Language: C++
6  Date: $Date: 2009-07-03 18:41:50 $
7  Version: $Revision: 1.67 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 #ifdef _MSC_VER
18 #pragma warning( disable : 4611 )
19 #endif
20 
21 #include "itkTIFFImageIO.h"
22 #include "itkRGBPixel.h"
23 #include "itkRGBAPixel.h"
24 #include <itksys/SystemTools.hxx>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include <sys/stat.h>
30 
31 #include "itk_tiff.h"
32 
33 namespace itk
34 {
35 
37 {
38 public:
40  int Initialize();
41  void Clean();
42  int CanRead();
43  int Open( const char *filename );
44  TIFF * m_Image;
45  bool m_IsOpen;
46  unsigned int m_Width;
47  unsigned int m_Height;
48  unsigned short m_NumberOfPages;
49  unsigned short m_CurrentPage;
50  unsigned short m_SamplesPerPixel;
51  unsigned short m_Compression;
52  unsigned short m_BitsPerSample;
53  unsigned short m_Photometrics;
55  unsigned short m_PlanarConfig;
56  unsigned short m_Orientation;
57  uint32 m_TileDepth;
58  unsigned int m_TileRows;
59  unsigned int m_TileColumns;
60  unsigned int m_TileWidth;
61  unsigned int m_TileHeight;
62  unsigned short m_NumberOfTiles;
63  unsigned int m_SubFiles;
64  unsigned int m_ResolutionUnit;
68 };
69 
70 int TIFFReaderInternal::Open( const char *filename )
71 {
72  this->Clean();
73  struct stat fs;
74  if ( stat(filename, &fs) )
75  {
76  return 0;
77  }
78 
79  this->m_Image = TIFFOpen(filename, "r");
80  if ( !this->m_Image)
81  {
82  this->Clean();
83  return 0;
84  }
85  if ( !this->Initialize() )
86  {
87  this->Clean();
88  return 0;
89  }
90 
91  this->m_IsOpen = true;
92  return 1;
93 }
94 
96 {
97  if ( this->m_Image )
98  {
99  TIFFClose(this->m_Image);
100  }
101  this->m_Image=NULL;
102  this->m_Width = 0;
103  this->m_Height = 0;
104  this->m_SamplesPerPixel = 0;
105  this->m_Compression = 0;
106  this->m_BitsPerSample = 0;
107  this->m_Photometrics = 0;
109  this->m_PlanarConfig = 0;
110  this->m_TileDepth = 0;
111  this->m_CurrentPage = 0;
112  this->m_NumberOfPages = 0;
113  this->m_NumberOfTiles = 0;
114  this->m_TileRows = 0;
115  this->m_TileColumns = 0;
116  this->m_TileWidth = 0;
117  this->m_TileHeight = 0;
118  this->m_XResolution = 1;
119  this->m_YResolution = 1;
120  this->m_SubFiles = 0;
121  this->m_SampleFormat = 1;
122  this->m_ResolutionUnit = 1; // none
123  this->m_IsOpen = false;
124 }
125 
127 {
128  this->m_Image = NULL;
129  this->Clean();
130 }
131 
133 {
134  if ( this->m_Image )
135  {
136  if ( !TIFFGetField(this->m_Image, TIFFTAG_IMAGEWIDTH, &this->m_Width) ||
137  !TIFFGetField(this->m_Image, TIFFTAG_IMAGELENGTH, &this->m_Height) )
138  {
139  return 0;
140  }
141 
142  // Get the resolution in each direction
143  TIFFGetField(this->m_Image,
144  TIFFTAG_XRESOLUTION, &this->m_XResolution);
145  TIFFGetField(this->m_Image,
146  TIFFTAG_YRESOLUTION, &this->m_YResolution);
147  TIFFGetField(this->m_Image,
148  TIFFTAG_RESOLUTIONUNIT, &this->m_ResolutionUnit);
149 
150  // Check the number of pages. First by looking at the number of directories
151  this->m_NumberOfPages = TIFFNumberOfDirectories(this->m_Image);
152 
153  if(this->m_NumberOfPages == 0)
154  {
155  if ( !TIFFGetField(this->m_Image,
156  TIFFTAG_PAGENUMBER,&this->m_CurrentPage,
157  &this->m_NumberOfPages))
158  {
159  // Check the Image Description tag to know the number of images
160  // This is used by ImageJ
161  char** description = new char*[255];
162  if (TIFFGetField(this->m_Image,TIFFTAG_IMAGEDESCRIPTION,description))
163  {
164  // look for the number of images
165  std::string desc = description[0];
166  int pos = desc.find("images=");
167  int pos2 = desc.find("\n");
168  if( (pos != -1) && (pos2 != -1))
169  {
170  this->m_NumberOfPages = atoi(desc.substr(pos+7,pos2-pos-7).c_str());
171  }
172  }
173  }
174  }
175 
176  // If the number of pages is still zero we look if the image is tiled
177  if(this->m_NumberOfPages == 0 && TIFFIsTiled(this->m_Image))
178  {
179  this->m_NumberOfTiles = TIFFNumberOfTiles(this->m_Image);
180 
181  if ( !TIFFGetField(this->m_Image,TIFFTAG_TILEWIDTH,&this->m_TileWidth)
182  || !TIFFGetField(this->m_Image,TIFFTAG_TILELENGTH,&this->m_TileHeight))
183  {
184  itkGenericExceptionMacro(
185  << "Cannot read tile width and tile length from file" );
186  }
187  else
188  {
189  this->m_TileRows = this->m_Height/this->m_TileHeight;
190  this->m_TileColumns = this->m_Width/this->m_TileWidth;
191  }
192  }
193 
194  // Checking if the TIFF contains subfiles
195  if(this->m_NumberOfPages > 1)
196  {
197  this->m_SubFiles = 0;
198 
199  for(unsigned int page = 0;page<this->m_NumberOfPages;page++)
200  {
201  int32 subfiletype = 6;
202  if(TIFFGetField(this->m_Image, TIFFTAG_SUBFILETYPE, &subfiletype))
203  {
204  if(subfiletype == 0)
205  {
206  this->m_SubFiles += 1;
207  }
208  }
209  TIFFReadDirectory(this->m_Image);
210  }
211 
212  // Set the directory to the first image
213  TIFFSetDirectory(this->m_Image,0);
214  }
215 
216  TIFFGetFieldDefaulted(this->m_Image, TIFFTAG_ORIENTATION,
217  &this->m_Orientation);
218  TIFFGetFieldDefaulted(this->m_Image, TIFFTAG_SAMPLESPERPIXEL,
219  &this->m_SamplesPerPixel);
220  TIFFGetFieldDefaulted(this->m_Image, TIFFTAG_COMPRESSION, &this->m_Compression);
221  TIFFGetFieldDefaulted(this->m_Image, TIFFTAG_BITSPERSAMPLE,
222  &this->m_BitsPerSample);
223  TIFFGetFieldDefaulted(this->m_Image, TIFFTAG_PLANARCONFIG, &this->m_PlanarConfig);
224  TIFFGetFieldDefaulted(this->m_Image, TIFFTAG_SAMPLEFORMAT, &this->m_SampleFormat);
225 
226  // If TIFFGetField returns false, there's no Photometric Interpretation
227  // set for this image, but that's a required field so we set a warning flag.
228  // (Because the "Photometrics" field is an enum, we can't rely on setting
229  // this->m_Photometrics to some signal value.)
230  if (TIFFGetField(this->m_Image, TIFFTAG_PHOTOMETRIC, &this->m_Photometrics))
231  {
233  }
234  else
235  {
237  }
238  if ( !TIFFGetField(this->m_Image, TIFFTAG_TILEDEPTH, &this->m_TileDepth) )
239  {
240  this->m_TileDepth = 0;
241  }
242  }
243 
244  return 1;
245 }
246 
248 {
249  return ( this->m_Image && ( this->m_Width > 0 ) && ( this->m_Height > 0 ) &&
250  ( this->m_SamplesPerPixel > 0 ) &&
251  ( this->m_Compression == COMPRESSION_NONE ||
252  this->m_Compression == COMPRESSION_PACKBITS ||
253  this->m_Compression == COMPRESSION_LZW
254  ) &&
256  ( this->m_Photometrics == PHOTOMETRIC_RGB ||
257  this->m_Photometrics == PHOTOMETRIC_MINISWHITE ||
258  this->m_Photometrics == PHOTOMETRIC_MINISBLACK ||
259  this->m_Photometrics == PHOTOMETRIC_PALETTE ) &&
260  ( this->m_PlanarConfig == PLANARCONFIG_CONTIG ) &&
261  ( !this->m_TileDepth ) &&
262  ( this->m_BitsPerSample == 8 || this->m_BitsPerSample == 16 ) );
263 }
264 
265 bool TIFFImageIO::CanReadFile(const char* file)
266 {
267  // First check the extension
268  std::string filename = file;
269  if( filename == "" )
270  {
271  itkDebugMacro(<<"No filename specified.");
272  return false;
273  }
274 
275  // Now check if this is a valid TIFF image
276  TIFFErrorHandler save = TIFFSetErrorHandler(0);
277  int res = m_InternalImage->Open(file);
278  if (res)
279  {
280  TIFFSetErrorHandler(save);
281  return true;
282  }
284  TIFFSetErrorHandler(save);
285  return false;
286 }
287 
291  unsigned int width,
292  unsigned int height )
293 {
294  unsigned int isize = TIFFScanlineSize(m_InternalImage->m_Image);
295  unsigned int cc;
296  int row;
297  tdata_t buf = _TIFFmalloc(isize);
298 
299  int inc = 1;
300 
301  if(m_ComponentType == UCHAR)
302  {
303  unsigned char* image;
304  if (m_InternalImage->m_PlanarConfig == PLANARCONFIG_CONTIG)
305  {
306  for ( row = 0; row < (int)height; row ++ )
307  {
308  if (TIFFReadScanline(m_InternalImage->m_Image, buf, row, 0) <= 0)
309  {
310  itkExceptionMacro( << "Problem reading the row: " << row );
311  break;
312  }
313 
314  if (m_InternalImage->m_Orientation == ORIENTATION_TOPLEFT)
315  {
316  image = reinterpret_cast<unsigned char*>(out) + row * width * inc;
317  }
318  else
319  {
320  image = reinterpret_cast<unsigned char*>(out) + width * inc * (height - (row + 1));
321  }
322 
323  for (cc = 0; cc < isize;
325  {
326  inc = this->EvaluateImageAt( image,
327  static_cast<unsigned char *>(buf) +
328  cc );
329  image += inc;
330  }
331  }
332  }
333  else if(m_InternalImage->m_PlanarConfig == PLANARCONFIG_SEPARATE)
334  {
335  uint32 s;
336  uint32 nsamples = 0;
337  TIFFGetField(m_InternalImage->m_Image, TIFFTAG_SAMPLESPERPIXEL, &nsamples);
338  for (s = 0; s < nsamples; s++)
339  {
340  for ( row = 0; row < (int)height; row ++ )
341  {
342  if (TIFFReadScanline(m_InternalImage->m_Image, buf, row, s) <= 0)
343  {
344  itkExceptionMacro( << "Problem reading the row: " << row );
345  break;
346  }
347 
348  inc = 3;
349 
350  if (m_InternalImage->m_Orientation == ORIENTATION_TOPLEFT)
351  {
352  image = reinterpret_cast<unsigned char*>(out) + row * width * inc;
353  }
354  else
355  {
356  image = reinterpret_cast<unsigned char*>(out) + width * inc * (height - (row + 1));
357  }
358 
359  // We translate the output pixel to be on the right RGB
360  image += s;
361  for (cc = 0; cc < isize;
362  cc += 1)
363  {
364  (*image) = *(static_cast<unsigned char *>(buf) + cc);
365  inc = 3;
366  image += inc;
367  }
368  }
369  }
370  }
371  }
372  else if(m_ComponentType == USHORT)
373  {
374  isize /= 2;
375  unsigned short* image;
376  if (m_InternalImage->m_PlanarConfig == PLANARCONFIG_CONTIG)
377  {
378  for ( row = 0; row < (int)height; row ++ )
379  {
380  if (TIFFReadScanline(m_InternalImage->m_Image, buf, row, 0) <= 0)
381  {
382  itkExceptionMacro( << "Problem reading the row: " << row );
383  break;
384  }
385 
386  if (m_InternalImage->m_Orientation == ORIENTATION_TOPLEFT)
387  {
388  image = reinterpret_cast<unsigned short*>(out) + row * width * inc;
389  }
390  else
391  {
392  image = reinterpret_cast<unsigned short*>(out) + width * inc * (height - (row + 1));
393  }
394 
395  for (cc = 0; cc < isize;
397  {
398  inc = this->EvaluateImageAt( image,
399  static_cast<unsigned short *>(buf) +
400  cc );
401  image += inc;
402  }
403  }
404  }
405  else if(m_InternalImage->m_PlanarConfig == PLANARCONFIG_SEPARATE)
406  {
407  uint32 s, nsamples;
408  TIFFGetField(m_InternalImage->m_Image, TIFFTAG_SAMPLESPERPIXEL, &nsamples);
409  for (s = 0; s < nsamples; s++)
410  {
411  for ( row = 0; row < (int)height; row ++ )
412  {
413  if (TIFFReadScanline(m_InternalImage->m_Image, buf, row, s) <= 0)
414  {
415  itkExceptionMacro( << "Problem reading the row: " << row );
416  break;
417  }
418 
419  if (m_InternalImage->m_Orientation == ORIENTATION_TOPLEFT)
420  {
421  image = reinterpret_cast<unsigned short*>(out) + row * width * inc;
422  }
423  else
424  {
425  image = reinterpret_cast<unsigned short*>(out) + width * inc * (height - (row + 1));
426  }
427  // We translate the output pixel to be on the right RGB
428  image += s;
429  for (cc = 0; cc < isize;
430  cc += 1)
431  {
432  (*image) = *(static_cast<unsigned short *>(buf) + cc);
433  inc = 3;
434  image += inc;
435  }
436  }
437  }
438  }
439  }
440  _TIFFfree(buf);
441 }
442 
443 
445  unsigned int width,
446  unsigned int height )
447 {
448  unsigned int isize = TIFFScanlineSize(m_InternalImage->m_Image);
449  unsigned int cc;
450  int row, inc;
451  tdata_t buf = _TIFFmalloc(isize);
452 
453  if ( m_InternalImage->m_PlanarConfig != PLANARCONFIG_CONTIG )
454  {
455  itkExceptionMacro( << "This reader can only do PLANARCONFIG_CONTIG" );
456  return;
457  }
458 
459  switch ( this->GetFormat() )
460  {
463  inc = 1;
464  break;
465  case TIFFImageIO::RGB_:
467  break;
469  inc = 3;
470  break;
471  default:
472  inc = 1;
473  break;
474  }
475 
476  if(m_ComponentType == UCHAR)
477  {
478  unsigned char* image;
479  if (m_InternalImage->m_PlanarConfig == PLANARCONFIG_CONTIG)
480  {
481  for ( row = 0; row < (int)height; row ++ )
482  {
483  if (TIFFReadScanline(m_InternalImage->m_Image, buf, row, 0) <= 0)
484  {
485  itkExceptionMacro( << "Problem reading the row: " << row );
486  break;
487  }
488 
489  if (m_InternalImage->m_Orientation == ORIENTATION_TOPLEFT)
490  {
491  image = reinterpret_cast<unsigned char*>(out) + row * width * inc;
492  }
493  else
494  {
495  image = reinterpret_cast<unsigned char*>(out) + width * inc * (height - (row + 1));
496  }
497 
498  for (cc = 0; cc < isize;
500  {
501  inc = this->EvaluateImageAt( image,
502  static_cast<unsigned char *>(buf) +
503  cc );
504  image += inc;
505  }
506  }
507  }
508  else if(m_InternalImage->m_PlanarConfig == PLANARCONFIG_SEPARATE)
509  {
510  uint32 s;
511  uint32 nsamples;
512  TIFFGetField(m_InternalImage->m_Image, TIFFTAG_SAMPLESPERPIXEL, &nsamples);
513  for (s = 0; s < nsamples; s++)
514  {
515  for ( row = 0; row < (int)height; row ++ )
516  {
517  if (TIFFReadScanline(m_InternalImage->m_Image, buf, row, s) <= 0)
518  {
519  itkExceptionMacro( << "Problem reading the row: " << row );
520  break;
521  }
522 
523  inc = 3;
524  if (m_InternalImage->m_Orientation == ORIENTATION_TOPLEFT)
525  {
526  image = reinterpret_cast<unsigned char*>(out) + row * width * inc;
527  }
528  else
529  {
530  image = reinterpret_cast<unsigned char*>(out) + width * inc * (height - (row + 1));
531  }
532 
533  for (cc = 0; cc < isize;
535  {
536  inc = this->EvaluateImageAt( image,
537  static_cast<unsigned char *>(buf) +
538  cc );
539  image += inc;
540  }
541  }
542  }
543  }
544  }
545  else if(m_ComponentType == CHAR)
546  {
547  char* image;
548  if (m_InternalImage->m_PlanarConfig == PLANARCONFIG_CONTIG)
549  {
550  for ( row = 0; row < (int)height; row ++ )
551  {
552  if (TIFFReadScanline(m_InternalImage->m_Image, buf, row, 0) <= 0)
553  {
554  itkExceptionMacro( << "Problem reading the row: " << row );
555  break;
556  }
557 
558  if (m_InternalImage->m_Orientation == ORIENTATION_TOPLEFT)
559  {
560  image = reinterpret_cast<char*>(out) + row * width * inc;
561  }
562  else
563  {
564  image = reinterpret_cast<char*>(out) + width * inc * (height - (row + 1));
565  }
566 
567  for (cc = 0; cc < isize;
569  {
570  inc = this->EvaluateImageAt( image,
571  static_cast<char *>(buf) +
572  cc );
573  image += inc;
574  }
575  }
576  }
577  else if(m_InternalImage->m_PlanarConfig == PLANARCONFIG_SEPARATE)
578  {
579  uint32 s;
580  uint32 nsamples;
581  TIFFGetField(m_InternalImage->m_Image, TIFFTAG_SAMPLESPERPIXEL, &nsamples);
582  for (s = 0; s < nsamples; s++)
583  {
584  for ( row = 0; row < (int)height; row ++ )
585  {
586  if (TIFFReadScanline(m_InternalImage->m_Image, buf, row, s) <= 0)
587  {
588  itkExceptionMacro( << "Problem reading the row: " << row );
589  break;
590  }
591 
592  inc = 3;
593  if (m_InternalImage->m_Orientation == ORIENTATION_TOPLEFT)
594  {
595  image = reinterpret_cast<char*>(out) + row * width * inc;
596  }
597  else
598  {
599  image = reinterpret_cast<char*>(out) + width * inc * (height - (row + 1));
600  }
601 
602  for (cc = 0; cc < isize;
604  {
605  inc = this->EvaluateImageAt( image,
606  static_cast<char *>(buf) +
607  cc );
608  image += inc;
609  }
610  }
611  }
612  }
613  }
614  else if(m_ComponentType == USHORT)
615  {
616  isize /= 2;
617  unsigned short* image;
618  if (m_InternalImage->m_PlanarConfig == PLANARCONFIG_CONTIG)
619  {
620  for ( row = 0; row < (int)height; row ++ )
621  {
622  if (TIFFReadScanline(m_InternalImage->m_Image, buf, row, 0) <= 0)
623  {
624  itkExceptionMacro( << "Problem reading the row: " << row );
625  break;
626  }
627 
628  if (m_InternalImage->m_Orientation == ORIENTATION_TOPLEFT)
629  {
630  image = reinterpret_cast<unsigned short*>(out) + row * width * inc;
631  }
632  else
633  {
634  image = reinterpret_cast<unsigned short*>(out) + width * inc * (height - (row + 1));
635  }
636 
637  for (cc = 0; cc < isize;
639  {
640  inc = this->EvaluateImageAt( image,
641  static_cast<unsigned short *>(buf) +
642  cc );
643  image += inc;
644  }
645  }
646  }
647  else if(m_InternalImage->m_PlanarConfig == PLANARCONFIG_SEPARATE)
648  {
649  uint32 s, nsamples;
650  TIFFGetField(m_InternalImage->m_Image, TIFFTAG_SAMPLESPERPIXEL, &nsamples);
651  for (s = 0; s < nsamples; s++)
652  {
653  for ( row = 0; row < (int)height; row ++ )
654  {
655  if (TIFFReadScanline(m_InternalImage->m_Image, buf, row, s) <= 0)
656  {
657  itkExceptionMacro( << "Problem reading the row: " << row );
658  break;
659  }
660 
661  if (m_InternalImage->m_Orientation == ORIENTATION_TOPLEFT)
662  {
663  image = reinterpret_cast<unsigned short*>(out) + row * width * inc;
664  }
665  else
666  {
667  image = reinterpret_cast<unsigned short*>(out) + width * inc * (height - (row + 1));
668  }
669  for (cc = 0; cc < isize;
671  {
672  inc = this->EvaluateImageAt( image,
673  static_cast<unsigned short *>(buf) +
674  cc );
675  image += inc;
676  }
677  }
678  }
679  }
680  }
681  // Short type
682  else if(m_ComponentType == SHORT)
683  {
684  isize /= 2;
685  short* image;
686  if (m_InternalImage->m_PlanarConfig == PLANARCONFIG_CONTIG)
687  {
688  for ( row = 0; row < (int)height; row ++ )
689  {
690  if (TIFFReadScanline(m_InternalImage->m_Image, buf, row, 0) <= 0)
691  {
692  itkExceptionMacro( << "Problem reading the row: " << row );
693  break;
694  }
695 
696  if (m_InternalImage->m_Orientation == ORIENTATION_TOPLEFT)
697  {
698  image = reinterpret_cast<short*>(out) + row * width * inc;
699  }
700  else
701  {
702  image = reinterpret_cast<short*>(out) + width * inc * (height - (row + 1));
703  }
704 
705  for (cc = 0; cc < isize;
707  {
708  inc = this->EvaluateImageAt( image,
709  static_cast<short *>(buf) +
710  cc );
711  image += inc;
712  }
713  }
714  }
715  else if(m_InternalImage->m_PlanarConfig == PLANARCONFIG_SEPARATE)
716  {
717  uint32 s, nsamples;
718  TIFFGetField(m_InternalImage->m_Image, TIFFTAG_SAMPLESPERPIXEL, &nsamples);
719  for (s = 0; s < nsamples; s++)
720  {
721  for ( row = 0; row < (int)height; row ++ )
722  {
723  if (TIFFReadScanline(m_InternalImage->m_Image, buf, row, s) <= 0)
724  {
725  itkExceptionMacro( << "Problem reading the row: " << row );
726  break;
727  }
728 
729  if (m_InternalImage->m_Orientation == ORIENTATION_TOPLEFT)
730  {
731  image = reinterpret_cast<short*>(out) + row * width * inc;
732  }
733  else
734  {
735  image = reinterpret_cast<short*>(out) + width * inc * (height - (row + 1));
736  }
737  for (cc = 0; cc < isize;
739  {
740  inc = this->EvaluateImageAt( image,
741  static_cast<short *>(buf) +
742  cc );
743  image += inc;
744  }
745  }
746  }
747  }
748  }
749  _TIFFfree(buf);
750 }
751 
752 
753 int TIFFImageIO::EvaluateImageAt( void* out, void* in )
754 {
755  unsigned char *image = (unsigned char*)out;
756  unsigned char *source = (unsigned char*)in;
757 
758  int increment;
759  unsigned short red, green, blue, alpha;
760  switch ( this->GetFormat() )
761  {
764  PHOTOMETRIC_MINISBLACK )
765  {
766  if(m_ComponentType == USHORT)
767  {
768  unsigned short *image_us = (unsigned short*)out;
769  unsigned short *source_us = (unsigned short*)in;
770  *image_us = *source_us;
771  }
772  else if(m_ComponentType == SHORT)
773  {
774  short *image_us = (short*)out;
775  short *source_us = (short*)in;
776  *image_us = *source_us;
777  }
778  else if(m_ComponentType == CHAR)
779  {
780  char *image_us = (char*)out;
781  char *source_us = (char*)in;
782  *image_us = *source_us;
783  }
784  else
785  {
786  *image = *source;
787  }
788  }
789  else
790  {
791  *image = ~( *source );
792  }
793  increment = 1;
794  break;
796  this->GetColor(*source, &red, &green, &blue);
797  *image = static_cast<unsigned char>(red >> 8);
798  increment = 1;
799  break;
800  case TIFFImageIO::RGB_:
801  if(m_ComponentType == USHORT)
802  {
803  unsigned short *image_us = (unsigned short*)out;
804  unsigned short *source_us = (unsigned short*)in;
805 
806  red = *(source_us);
807  green = *(source_us+1);
808  blue = *(source_us+2);
809  *(image_us) = red;
810  *(image_us+1) = green;
811  *(image_us+2) = blue;
813  {
814  alpha = *(source_us+3);
815  *(image_us+3) = 65535-alpha;
816  }
817  }
818  else
819  {
820  red = *(source);
821  green = *(source+1);
822  blue = *(source+2);
823  *(image) = red;
824  *(image+1) = green;
825  *(image+2) = blue;
827  {
828  alpha = *(source+3);
829  *(image+3) = 255-alpha;
830  }
831  }
832  increment = m_InternalImage->m_SamplesPerPixel;
833  break;
835  if(m_ComponentType == USHORT)
836  {
837  unsigned short *image_us = (unsigned short*)out;
838  unsigned short *source_us = (unsigned short*)in;
839  this->GetColor(*source_us, &red, &green, &blue);
840  *(image_us) = red << 8;
841  *(image_us+1) = green << 8;
842  *(image_us+2) = blue << 8;
843  }
844  else if(m_ComponentType == SHORT)
845  {
846  short *image_us = (short*)out;
847  short *source_us = (short*)in;
848  this->GetColor(*source_us, &red, &green, &blue);
849  *(image_us) = red << 8;
850  *(image_us+1) = green << 8;
851  *(image_us+2) = blue << 8;
852  }
853  else if(m_ComponentType == CHAR)
854  {
855  this->GetColor(*source, &red, &green, &blue);
856  *(image) = static_cast<char>(red >> 8);
857  *(image+1) = static_cast<char>(green >> 8);
858  *(image+2) = static_cast<char>(blue >> 8);
859  }
860  else
861  {
862  this->GetColor(*source, &red, &green, &blue);
863  *(image) = static_cast<unsigned char>(red >> 8);
864  *(image+1) = static_cast<unsigned char>(green >> 8);
865  *(image+2) = static_cast<unsigned char>(blue >> 8);
866  }
867  increment = 3;
868  break;
869  default:
870  return 0;
871  }
872 
873  return increment;
874 }
875 
876 
877 void TIFFImageIO::GetColor( int index, unsigned short *red,
878  unsigned short *green, unsigned short *blue )
879 {
880  *red = 0;
881  *green = 0;
882  *blue = 0;
883  if ( index < 0 )
884  {
885  itkExceptionMacro( << "Color index has to be greater than 0" );
886  return;
887  }
888  if ( m_TotalColors > 0 &&
890  {
891  if ( index >= m_TotalColors )
892  {
893  itkExceptionMacro( << "Color index has to be less than number of colors ("
894  << m_TotalColors << ")" );
895  return;
896  }
897  *red = *(m_ColorRed + index);
898  *green = *(m_ColorGreen + index);
899  *blue = *(m_ColorBlue + index);
900  return;
901  }
902 
903  unsigned short photometric;
904 
905  if (!TIFFGetField(m_InternalImage->m_Image, TIFFTAG_PHOTOMETRIC, &photometric))
906  {
907  if ( m_InternalImage->m_Photometrics != PHOTOMETRIC_PALETTE )
908  {
909  itkExceptionMacro( << "You can only access colors for palette images" );
910  return;
911  }
912  }
913 
914  unsigned short *red_orig, *green_orig, *blue_orig;
915 
917  {
918  case 1: case 2: case 4:
919  case 8: case 16:
920  break;
921  default:
922  itkExceptionMacro( << "Sorry, can not handle image with "
924  << "-bit samples" );
925  return;
926  }
927  if (!TIFFGetField(m_InternalImage->m_Image, TIFFTAG_COLORMAP,
928  &red_orig, &green_orig, &blue_orig))
929  {
930  itkExceptionMacro( << "Missing required \"Colormap\" tag" );
931  return;
932  }
934 
935  if ( index >= m_TotalColors )
936  {
937  itkExceptionMacro( << "Color index has to be less than number of colors ("
938  << m_TotalColors << ")" );
939  return;
940  }
941  m_ColorRed = red_orig;
942  m_ColorGreen = green_orig;
943  m_ColorBlue = blue_orig;
944 
945  *red = *(red_orig + index);
946  *green = *(green_orig + index);
947  *blue = *(blue_orig + index);
948 }
949 
950 
951 unsigned int TIFFImageIO::GetFormat( )
952 {
953  unsigned int cc;
954 
956  {
957  return m_ImageFormat;
958  }
959 
960 
961  switch ( m_InternalImage->m_Photometrics )
962  {
963  case PHOTOMETRIC_RGB:
964  case PHOTOMETRIC_YCBCR:
966  return m_ImageFormat;
967  case PHOTOMETRIC_MINISWHITE:
968  case PHOTOMETRIC_MINISBLACK:
970  return m_ImageFormat;
971  case PHOTOMETRIC_PALETTE:
972  for( cc=0; cc<256; cc++ )
973  {
974  unsigned short red, green, blue;
975  this->GetColor( cc, &red, &green, &blue );
976  if ( red != green || red != blue )
977  {
979  return m_ImageFormat;
980  }
981  }
983  return m_ImageFormat;
984  }
986  return m_ImageFormat;
987 }
988 
990 void TIFFImageIO::ReadTiles(void* buffer)
991 {
992  unsigned char* volume = reinterpret_cast<unsigned char*>(buffer);
993 
994  for(unsigned int col = 0;col<m_InternalImage->m_Width;col+=m_InternalImage->m_TileWidth)
995  {
996  for(unsigned int row = 0;row<m_InternalImage->m_Height;row+=m_InternalImage->m_TileHeight)
997  {
998  unsigned char *tempImage;
1000 
1001  if(TIFFReadTile(m_InternalImage->m_Image,tempImage, col,row,0,0)<0)
1002  {
1003  itkExceptionMacro( << "Cannot read tile : "<< row << "," << col << " from file" );
1004  if ( tempImage != buffer )
1005  {
1006  delete [] tempImage;
1007  }
1008 
1009  return;
1010  }
1011 
1012  unsigned int xx, yy;
1013  for ( yy = 0; yy < m_InternalImage->m_TileHeight; yy++ )
1014  {
1015  for ( xx = 0; xx < m_InternalImage->m_TileWidth; xx++ )
1016  {
1017  for(unsigned int i=0;i< m_InternalImage->m_SamplesPerPixel;i++)
1018  {
1019  *volume = *(tempImage++);
1020  volume++;
1021  }
1022  }
1023  }
1024  }
1025  }
1026 }
1027 
1029 void TIFFImageIO::ReadVolume(void* buffer)
1030 {
1031  int width = m_InternalImage->m_Width;
1032  int height = m_InternalImage->m_Height;
1033 
1034  for(unsigned int page = 0;page<m_InternalImage->m_NumberOfPages;page++)
1035  {
1037  {
1038  int32 subfiletype = 6;
1039  if(TIFFGetField(m_InternalImage->m_Image, TIFFTAG_SUBFILETYPE, &subfiletype))
1040  {
1041  if(subfiletype != 0)
1042  {
1043  TIFFReadDirectory(m_InternalImage->m_Image);
1044  continue;
1045  }
1046  }
1047  }
1048 
1049  // It is necessary to re-initialize the colors for each page so
1050  // that the colormap is reset in the GetColor method. This is
1051  // also true in the case that each slice has a different colormap.
1052  this->InitializeColors();
1053 
1054  // if we have a Zeiss image meaning that the SamplesPerPixel is 2
1056  {
1057  if(m_ComponentType == USHORT)
1058  {
1059  unsigned short* volume = reinterpret_cast<unsigned short*>(buffer);
1060  volume += width*height*m_InternalImage->m_SamplesPerPixel*page;
1061  this->ReadTwoSamplesPerPixelImage( volume, width, height );
1062  }
1063  else if(m_ComponentType == SHORT)
1064  {
1065  short* volume = reinterpret_cast<short*>(buffer);
1066  volume += width*height*m_InternalImage->m_SamplesPerPixel*page;
1067  this->ReadTwoSamplesPerPixelImage( volume, width, height );
1068  }
1069  else if(m_ComponentType == CHAR)
1070  {
1071  char* volume = reinterpret_cast<char*>(buffer);
1072  volume += width*height*m_InternalImage->m_SamplesPerPixel*page;
1073  this->ReadTwoSamplesPerPixelImage( volume, width, height );
1074  }
1075  else
1076  {
1077  unsigned char* volume = reinterpret_cast<unsigned char*>(buffer);
1078  volume += width*height*m_InternalImage->m_SamplesPerPixel*page;
1079  this->ReadTwoSamplesPerPixelImage( volume, width, height );
1080  }
1081  break;
1082  }
1083  else if ( !m_InternalImage->CanRead() )
1084  {
1085  uint32 *tempImage;
1086  tempImage = new uint32[ width * height ];
1087 
1088  if ( !TIFFReadRGBAImage(m_InternalImage->m_Image,
1089  width, height,
1090  tempImage, 1 ) )
1091  {
1092  itkExceptionMacro( << "Cannot read TIFF image or as a TIFF RGBA image" );
1093  if ( tempImage != buffer )
1094  {
1095  delete [] tempImage;
1096  }
1097  return;
1098  }
1099  int xx, yy;
1100  uint32* ssimage;
1101 
1102  if(m_ComponentType == USHORT)
1103  {
1104  unsigned short *fimage = (unsigned short *)buffer;
1105  fimage += width*height*4*page;
1106  for ( yy = 0; yy < height; yy ++ )
1107  {
1108  ssimage = tempImage + (height - yy - 1) * width;
1109  for ( xx = 0; xx < width; xx++ )
1110  {
1111  unsigned short red = static_cast<unsigned short>(TIFFGetR(*ssimage));
1112  unsigned short green = static_cast<unsigned short>(TIFFGetG(*ssimage));
1113  unsigned short blue = static_cast<unsigned short>(TIFFGetB(*ssimage));
1114  unsigned short alpha = static_cast<unsigned short>(TIFFGetA(*ssimage));
1115 
1116  *(fimage ) = red;
1117  *(fimage+1) = green;
1118  *(fimage+2) = blue;
1119  *(fimage+3) = alpha;
1120  fimage += 4;
1121  ssimage ++;
1122  }
1123  }
1124  }
1125  else if(m_ComponentType == SHORT)
1126  {
1127  short *fimage = (short *)buffer;
1128  fimage += width*height*4*page;
1129  for ( yy = 0; yy < height; yy ++ )
1130  {
1131  ssimage = tempImage + (height - yy - 1) * width;
1132  for ( xx = 0; xx < width; xx++ )
1133  {
1134  short red = static_cast<short>(TIFFGetR(*ssimage));
1135  short green = static_cast<short>(TIFFGetG(*ssimage));
1136  short blue = static_cast<short>(TIFFGetB(*ssimage));
1137  short alpha = static_cast<short>(TIFFGetA(*ssimage));
1138 
1139  *(fimage ) = red;
1140  *(fimage+1) = green;
1141  *(fimage+2) = blue;
1142  *(fimage+3) = alpha;
1143  fimage += 4;
1144  ssimage ++;
1145  }
1146  }
1147  }
1148  else if(m_ComponentType == CHAR)
1149  {
1150  char *fimage = (char *)buffer;
1151  fimage += width*height*4*page;
1152  for ( yy = 0; yy < height; yy ++ )
1153  {
1154  ssimage = tempImage + (height - yy - 1) * width;
1155  for ( xx = 0; xx < width; xx++ )
1156  {
1157  char red = static_cast<char>(TIFFGetR(*ssimage));
1158  char green = static_cast<char>(TIFFGetG(*ssimage));
1159  char blue = static_cast<char>(TIFFGetB(*ssimage));
1160  char alpha = static_cast<char>(TIFFGetA(*ssimage));
1161 
1162  *(fimage ) = red;
1163  *(fimage+1) = green;
1164  *(fimage+2) = blue;
1165  *(fimage+3) = alpha;
1166  fimage += 4;
1167  ssimage ++;
1168  }
1169  }
1170  }
1171  else
1172  {
1173  unsigned char *fimage = (unsigned char *)buffer;
1174  fimage += width*height*4*page/2;
1175  for ( yy = 0; yy < height; yy ++ )
1176  {
1177  ssimage = tempImage + (height - yy - 1) * width;
1178  for ( xx = 0; xx < width; xx++ )
1179  {
1180  unsigned char red = static_cast<unsigned char>(TIFFGetR(*ssimage));
1181  unsigned char green = static_cast<unsigned char>(TIFFGetG(*ssimage));
1182  unsigned char blue = static_cast<unsigned char>(TIFFGetB(*ssimage));
1183  unsigned char alpha = static_cast<unsigned char>(TIFFGetA(*ssimage));
1184 
1185  *(fimage ) = red;
1186  *(fimage+1) = green;
1187  *(fimage+2) = blue;
1188  *(fimage+3) = alpha;
1189  fimage += 4;
1190  ssimage ++;
1191  }
1192  }
1193  }
1194  if ( tempImage != 0 && tempImage != buffer )
1195  {
1196  delete [] tempImage;
1197  }
1198  }
1199  else
1200  {
1201  unsigned int format = this->GetFormat();
1202 
1203  switch ( format )
1204  {
1206  case TIFFImageIO::RGB_:
1208  if(m_ComponentType == USHORT)
1209  {
1210  unsigned short* volume = reinterpret_cast<unsigned short*>(buffer);
1211  volume += width*height*m_InternalImage->m_SamplesPerPixel*page;
1212  this->ReadGenericImage( volume, width, height );
1213  }
1214  else if(m_ComponentType == SHORT)
1215  {
1216  short* volume = reinterpret_cast<short*>(buffer);
1217  volume += width*height*m_InternalImage->m_SamplesPerPixel*page;
1218  this->ReadGenericImage( volume, width, height );
1219  }
1220  else if(m_ComponentType == CHAR)
1221  {
1222  char* volume = reinterpret_cast<char*>(buffer);
1223  volume += width*height*m_InternalImage->m_SamplesPerPixel*page;
1224  this->ReadGenericImage( volume, width, height );
1225  }
1226  else
1227  {
1228  unsigned char* volume = reinterpret_cast<unsigned char*>(buffer);
1229  volume += width*height*m_InternalImage->m_SamplesPerPixel*page;
1230  this->ReadGenericImage( volume, width, height );
1231  }
1232  break;
1234  // This differs from PALLETTE_GRAYSCALE only in that the
1235  // volume is incremented by 3 times more since the colormap
1236  // consists of RGB.
1237  if(m_ComponentType == USHORT)
1238  {
1239  unsigned short* volume = reinterpret_cast<unsigned short*>(buffer);
1240  volume += width*height*m_InternalImage->m_SamplesPerPixel*page*3;
1241  this->ReadGenericImage( volume, width, height );
1242  }
1243  else if(m_ComponentType == SHORT)
1244  {
1245  short* volume = reinterpret_cast<short*>(buffer);
1246  volume += width*height*m_InternalImage->m_SamplesPerPixel*page*3;
1247  this->ReadGenericImage( volume, width, height );
1248  }
1249  else if(m_ComponentType == CHAR)
1250  {
1251  char* volume = reinterpret_cast<char*>(buffer);
1252  volume += width*height*m_InternalImage->m_SamplesPerPixel*page*3;
1253  this->ReadGenericImage( volume, width, height );
1254  }
1255  else
1256  {
1257  unsigned char* volume = reinterpret_cast<unsigned char*>(buffer);
1258  volume += width*height*m_InternalImage->m_SamplesPerPixel*page*3;
1259  this->ReadGenericImage( volume, width, height );
1260  }
1261  break;
1262  default:
1263  return;
1264  }
1265  }
1266  TIFFReadDirectory(m_InternalImage->m_Image);
1267  }
1268 }
1269 
1270 
1271 void TIFFImageIO::Read(void* buffer)
1272 {
1273  if ( m_InternalImage->m_Compression == COMPRESSION_OJPEG )
1274  {
1275  itkExceptionMacro( << "This reader cannot read old JPEG compression" );
1276  return;
1277  }
1278 
1279  // The IO region should be of dimensions 3 otherwise we read only the first page
1280  if(m_InternalImage->m_NumberOfPages>0 && this->GetIORegion().GetImageDimension()>2)
1281  {
1282  this->ReadVolume(buffer);
1284  return;
1285  }
1286 
1287  if(m_InternalImage->m_NumberOfTiles>0 && this->GetIORegion().GetImageDimension()>2)
1288  {
1289  this->ReadTiles(buffer);
1291  return;
1292  }
1293 
1294  int width = m_InternalImage->m_Width;
1295  int height = m_InternalImage->m_Height;
1296 
1297 
1298  if ( !m_InternalImage->CanRead() )
1299  {
1300  uint32 *tempImage;
1301  tempImage = new uint32[ width * height ];
1302 
1303  if ( !TIFFReadRGBAImage(m_InternalImage->m_Image,
1304  width, height,
1305  tempImage, 1 ) )
1306  {
1307  itkExceptionMacro( << "Cannot read TIFF image or as a TIFF RGBA image" );
1308  if ( tempImage != buffer )
1309  {
1310  delete [] tempImage;
1311  }
1312 
1314  return;
1315  }
1316  int xx, yy;
1317  uint32* ssimage;
1318  unsigned char *fimage = (unsigned char *)buffer;
1319 
1320  for ( yy = 0; yy < height; yy ++ )
1321  {
1322  ssimage = tempImage + (height - yy - 1) * width;
1323  for ( xx = 0; xx < width; xx++ )
1324  {
1325  unsigned char red = static_cast<unsigned char>(TIFFGetR(*ssimage));
1326  unsigned char green = static_cast<unsigned char>(TIFFGetG(*ssimage));
1327  unsigned char blue = static_cast<unsigned char>(TIFFGetB(*ssimage));
1328  unsigned char alpha = static_cast<unsigned char>(TIFFGetA(*ssimage));
1329 
1330  *(fimage ) = red;
1331  *(fimage+1) = green;
1332  *(fimage+2) = blue;
1333  *(fimage+3) = alpha;
1334  fimage += 4;
1335 
1336  ssimage ++;
1337  }
1338  }
1339 
1340  if ( tempImage != 0 && tempImage != buffer )
1341  {
1342  delete [] tempImage;
1343  }
1345  return;
1346  }
1347 
1348  unsigned int format = this->GetFormat();
1349 
1350  switch ( format )
1351  {
1353  case TIFFImageIO::RGB_:
1356  this->ReadGenericImage( buffer, width, height );
1357  break;
1358  default:
1359  return;
1360  }
1362 }
1363 
1364 
1366 {
1367  this->SetNumberOfDimensions(2);
1368  m_PixelType = SCALAR;
1370 
1371  this->InitializeColors();
1373 
1374  m_Spacing[0] = 1.0;
1375  m_Spacing[1] = 1.0;
1376 
1377  m_Origin[0] = 0.0;
1378  m_Origin[1] = 0.0;
1379 
1381 
1382  this->AddSupportedWriteExtension(".tif");
1383  this->AddSupportedWriteExtension(".TIF");
1384  this->AddSupportedWriteExtension(".tiff");
1385  this->AddSupportedWriteExtension(".TIFF");
1386 
1387  this->AddSupportedReadExtension(".tif");
1388  this->AddSupportedReadExtension(".TIF");
1389  this->AddSupportedReadExtension(".tiff");
1390  this->AddSupportedReadExtension(".TIFF");
1391 
1392 }
1393 
1395 {
1397  delete m_InternalImage;
1398 }
1399 
1400 void TIFFImageIO::PrintSelf(std::ostream& os, Indent indent) const
1401 {
1402  Superclass::PrintSelf(os, indent);
1403  os << indent << "Compression: " << m_Compression << "\n";
1404 }
1405 
1407 {
1408  m_ColorRed = 0;
1409  m_ColorGreen = 0;
1410  m_ColorBlue = 0;
1411  m_TotalColors = -1;
1413 }
1414 
1416 {
1417  // If the internal image was not open we open it.
1418  // This is usually done when the user sets the ImageIO manually
1420  {
1421  if(!this->CanReadFile(m_FileName.c_str()))
1422  {
1423  itkExceptionMacro(<<"Cannot open the file!");
1424  return;
1425  }
1426  }
1427 
1428  m_Spacing[0] = 1.0;
1429  m_Spacing[1] = 1.0;
1430 
1431  // If we have some spacing information we use it
1435  )
1436  {
1437  if(m_InternalImage->m_ResolutionUnit == 2) // inches
1438  {
1441  }
1442  else if(m_InternalImage->m_ResolutionUnit == 3) // cm
1443  {
1446  }
1447  }
1448 
1449  m_Origin[0] = 0.0;
1450  m_Origin[1] = 0.0;
1451 
1452  int width = m_InternalImage->m_Width;
1453  int height = m_InternalImage->m_Height;
1454 
1455  m_Dimensions[0] = width;
1456  m_Dimensions[1] = height;
1457 
1458  switch ( this->GetFormat() )
1459  {
1462  this->SetNumberOfComponents( 1 );
1463  this->SetPixelType(SCALAR);
1464  break;
1465  case TIFFImageIO::RGB_:
1467  this->SetPixelType(RGB);
1468  break;
1470  this->SetNumberOfComponents( 3 );
1471  this->SetPixelType(RGB);
1472  break;
1473  default:
1474  this->SetNumberOfComponents( 4 );
1475  this->SetPixelType(RGBA);
1476  }
1477 
1478  if ( !m_InternalImage->CanRead() )
1479  {
1480  this->SetNumberOfComponents( 4 );
1481  this->SetPixelType(RGBA);
1482  }
1483 
1484  if (m_InternalImage->m_BitsPerSample <= 8)
1485  {
1487  {
1489  }
1490  else
1491  {
1493  }
1494  }
1495  else
1496  {
1498  {
1500  }
1501  else
1502  {
1504  }
1505  }
1506 
1507  // We check if we have a Zeiss image.
1508  // Meaning that the SamplesPerPixel is 2 but the image should be treated as
1509  // an RGB image.
1511  {
1512  this->SetNumberOfComponents(3);
1513  this->SetPixelType(RGB);
1514  }
1515 
1516  // if the tiff file is multi-pages
1518  {
1519  this->SetNumberOfDimensions(3);
1521  {
1523  }
1524  else
1525  {
1527  }
1528  m_Spacing[2] = 1.0;
1529  m_Origin[2] = 0.0;
1530  }
1531 
1532  // if the tiff is tiled
1534  {
1535  this->SetNumberOfDimensions(3);
1539  m_Spacing[2] = 1.0;
1540  m_Origin[2] = 0.0;
1541  }
1542 
1543  return;
1544 }
1545 
1546 bool TIFFImageIO::CanWriteFile( const char * name )
1547 {
1548  std::string filename = name;
1549 
1550  if (filename == "")
1551  {
1552  return false;
1553  }
1554 
1555  std::string::size_type TIFFPos = filename.rfind(".TIFF");
1556  if ( (TIFFPos != std::string::npos)
1557  && (TIFFPos == filename.length() - 5) )
1558  {
1559  return true;
1560  }
1561 
1562  TIFFPos = filename.rfind(".tiff");
1563  if ( (TIFFPos != std::string::npos)
1564  && (TIFFPos == filename.length() - 5) )
1565  {
1566  return true;
1567  }
1568 
1569  TIFFPos = filename.rfind(".tif");
1570  if ( (TIFFPos != std::string::npos)
1571  && (TIFFPos == filename.length() - 4) )
1572  {
1573  return true;
1574  }
1575 
1576 
1577  TIFFPos = filename.rfind(".TIF");
1578  if ( (TIFFPos != std::string::npos)
1579  && (TIFFPos == filename.length() - 4) )
1580  {
1581  return true;
1582  }
1583 
1584 
1585  return false;
1586 }
1587 
1588 
1590 {
1591 }
1592 
1593 void TIFFImageIO::Write(const void* buffer)
1594 {
1595  if( m_NumberOfDimensions == 2 || m_NumberOfDimensions == 3 )
1596  {
1597  this->InternalWrite(buffer);
1598  }
1599  else
1600  {
1601  itkExceptionMacro(<<"TIFF Writer can only write 2-d or 3-d images");
1602  }
1603 }
1604 
1606 {
1607 public:
1608  // Writing file no reading
1609  static tsize_t TIFFRead(thandle_t, tdata_t, tsize_t) { return 0; }
1610 
1611  // Write data
1612  static tsize_t TIFFWrite(thandle_t fd, tdata_t buf, tsize_t size)
1613  {
1614  std::ostream *out = reinterpret_cast<std::ostream *>(fd);
1615  out->write(static_cast<char *>(buf), size);
1616  return out->fail() ? static_cast<tsize_t>(0) : size;
1617  }
1618 
1619  static toff_t TIFFSeek(thandle_t fd, toff_t off, int whence)
1620  {
1621 #ifdef __sgi
1622  int need;
1623 #endif
1624  std::ostream *out = reinterpret_cast<std::ostream *>(fd);
1625  switch (whence)
1626  {
1627  case SEEK_SET:
1628 #ifdef __sgi
1629  out->seekp(0, std::ios::end);
1630  need = static_cast<int>(off) - static_cast<int>(out->tellp());
1631  if (need > 0)
1632  {
1633  char buf[1] = {'\0'};
1634  for (int ii = 0; ii < need; ii++) out->write(buf,1);
1635  }
1636 #endif
1637  out->seekp(off, std::ios::beg);
1638  break;
1639  case SEEK_END:
1640  out->seekp(off, std::ios::end);
1641  break;
1642  case SEEK_CUR:
1643  out->seekp(off, std::ios::cur);
1644  break;
1645  default:
1646  return static_cast<toff_t>(out->tellp());
1647  }
1648  return static_cast<toff_t>(out->tellp());
1649  }
1650 
1651  static toff_t TIFFSize(thandle_t fd)
1652  {
1653  std::ostream *out = reinterpret_cast<std::ostream *>(fd);
1654  out->seekp(0, std::ios::end);
1655  return static_cast<toff_t>(out->tellp());
1656  }
1657 
1658  static int TIFFMapFile(thandle_t, tdata_t*, toff_t*) { return (0); }
1659  static void TIFFUnmapFile(thandle_t, tdata_t, toff_t) {}
1660 };
1661 
1662 void TIFFImageIO::InternalWrite(const void* buffer)
1663 {
1664  char *outPtr = (char *) buffer;
1665 
1666  unsigned int width, height, page, pages = 1;
1667  width = m_Dimensions[0];
1668  height = m_Dimensions[1];
1669  if( m_NumberOfDimensions == 3 )
1670  {
1671  pages = m_Dimensions[2];
1672  }
1673 
1674  int scomponents = this->GetNumberOfComponents();
1675  double resolution = -1;
1676  uint32 rowsperstrip = (uint32) -1;
1677  int bps;
1678 
1679  switch (this->GetComponentType())
1680  {
1681  case UCHAR:
1682  bps = 8;
1683  break;
1684  case CHAR:
1685  bps = 8;
1686  break;
1687  case USHORT:
1688  bps = 16;
1689  break;
1690  case SHORT:
1691  bps = 16;
1692  break;
1693  default:
1694  itkExceptionMacro(
1695  <<"TIFF supports unsigned/signed char and unsigned/signed short");
1696  }
1697 
1698  int predictor;
1699 
1700  TIFF *tif = TIFFOpen(m_FileName.c_str(), "w");
1701  if ( !tif )
1702  {
1703  itkExceptionMacro("Error while trying to open file for writing: "
1704  <<this->GetFileName()
1705  << std::endl
1706  << "Reason: "
1707  << itksys::SystemTools::GetLastSystemError());
1708  }
1709 
1710  if(this->GetComponentType() == SHORT
1711  || this->GetComponentType() == CHAR)
1712  {
1713  TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_INT);
1714  }
1715 
1716  uint32 w = width;
1717  uint32 h = height;
1718 
1719  if( m_NumberOfDimensions == 3)
1720  {
1721  TIFFCreateDirectory( tif );
1722  }
1723  for (page = 0; page < pages; page++)
1724  {
1725  TIFFSetDirectory( tif, page );
1726  TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, w);
1727  TIFFSetField(tif, TIFFTAG_IMAGELENGTH, h);
1728  TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
1729  TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, scomponents);
1730  TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); // Fix for stype
1731  TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1732  if(this->GetComponentType() == SHORT
1733  || this->GetComponentType() == CHAR)
1734  {
1735  TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_INT);
1736  }
1737  TIFFSetField(tif, TIFFTAG_SOFTWARE, "InsightToolkit");
1738 
1739  if ( scomponents > 3 )
1740  {
1741  // if number of scalar components is greater than 3, that means we assume
1742  // there is alpha.
1743  uint16 extra_samples = scomponents-3;
1744  uint16 *sample_info = new uint16[scomponents-3];
1745  sample_info[0]=EXTRASAMPLE_ASSOCALPHA;
1746  int cc;
1747  for ( cc = 1; cc < scomponents-3; cc ++ )
1748  {
1749  sample_info[cc] = EXTRASAMPLE_UNSPECIFIED;
1750  }
1751  TIFFSetField(tif,TIFFTAG_EXTRASAMPLES,extra_samples,
1752  sample_info);
1753  delete [] sample_info;
1754  }
1755 
1756  int compression;
1757 
1758  if(m_UseCompression)
1759  {
1760  switch ( m_Compression )
1761  {
1762  case TIFFImageIO::PackBits: compression = COMPRESSION_PACKBITS; break;
1763  case TIFFImageIO::JPEG: compression = COMPRESSION_JPEG; break;
1764  case TIFFImageIO::Deflate: compression = COMPRESSION_DEFLATE; break;
1765  case TIFFImageIO::LZW: compression = COMPRESSION_LZW; break;
1766  default: compression = COMPRESSION_NONE;
1767  }
1768  }
1769  else
1770  {
1771  compression = COMPRESSION_NONE;
1772  }
1773 
1774  TIFFSetField(tif, TIFFTAG_COMPRESSION, compression); // Fix for compression
1775 
1776  uint16 photometric = (scomponents ==1) ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB;
1777 
1778  if ( compression == COMPRESSION_JPEG )
1779  {
1780  TIFFSetField(tif, TIFFTAG_JPEGQUALITY, 75); // Parameter
1781  TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
1782  photometric = PHOTOMETRIC_YCBCR;
1783  }
1784  else if ( compression == COMPRESSION_LZW )
1785  {
1786  predictor = 2;
1787  TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor);
1788  itkDebugMacro( << "LZW compression is patented outside US so it is disabled" );
1789  }
1790  else if ( compression == COMPRESSION_DEFLATE )
1791  {
1792  predictor = 2;
1793  TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor);
1794  }
1795 
1796  TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric); // Fix for scomponents
1797 
1798  TIFFSetField(tif,
1799  TIFFTAG_ROWSPERSTRIP,
1800  TIFFDefaultStripSize(tif, rowsperstrip));
1801  if (resolution > 0)
1802  {
1803  TIFFSetField(tif, TIFFTAG_XRESOLUTION, resolution);
1804  TIFFSetField(tif, TIFFTAG_YRESOLUTION, resolution);
1805  TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
1806  }
1807 
1808  if( m_NumberOfDimensions == 3)
1809  {
1810  // We are writing single page of the multipage file
1811  TIFFSetField(tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
1812  // Set the page number
1813  TIFFSetField(tif, TIFFTAG_PAGENUMBER, page, pages);
1814  }
1815  int rowLength; // in bytes
1816 
1817  switch (this->GetComponentType())
1818  {
1819  case UCHAR:
1820  rowLength = sizeof(unsigned char);
1821  break;
1822  case USHORT:
1823  rowLength = sizeof(unsigned short);
1824  break;
1825  case CHAR:
1826  rowLength = sizeof(char);
1827  break;
1828  case SHORT:
1829  rowLength = sizeof(short);
1830  break;
1831  default:
1832  itkExceptionMacro(
1833  <<"TIFF supports unsigned/signed char and unsigned/signed short");
1834  }
1835 
1836  rowLength *= this->GetNumberOfComponents();
1837  rowLength *= width;
1838 
1839  int row = 0;
1840  for (unsigned int idx2 = 0; idx2 < height; idx2++)
1841  {
1842  if ( TIFFWriteScanline(tif, const_cast<char*>(outPtr), row, 0) < 0)
1843  {
1844  itkExceptionMacro( << "TIFFImageIO: error out of disk space" );
1845  break;
1846  }
1847  outPtr += rowLength;
1848  row++;
1849  }
1850 
1851  if(m_NumberOfDimensions == 3 )
1852  {
1853  TIFFWriteDirectory(tif);
1854  }
1855  }
1856  TIFFClose(tif);
1857 }
1858 
1859 bool TIFFImageIO::CanFindTIFFTag( unsigned int t )
1860 {
1861  // m_InternalImage needs to be valid
1862  if( !m_InternalImage )
1863  {
1864  itkExceptionMacro( << "Need to call CanReadFile before" );
1865  return false;
1866  }
1867 
1868  ttag_t tag = t; // 32bits integer
1869  const TIFFFieldInfo *fld = TIFFFieldWithTag( m_InternalImage->m_Image, tag );
1870  if( fld == NULL )
1871  {
1872  return false;
1873  }
1874  return true;
1875 }
1876 
1877 void *TIFFImageIO::ReadRawByteFromTag( unsigned int t, short &value_count )
1878 {
1879  // m_InternalImage needs to be valid
1880  if( !m_InternalImage )
1881  {
1882  itkExceptionMacro( << "Need to call CanReadFile before" );
1883  return NULL;
1884  }
1885  ttag_t tag = t;
1886  void *raw_data = NULL;
1887  const TIFFFieldInfo *fld = TIFFFieldWithTag( m_InternalImage->m_Image, tag );
1888  if( fld == NULL )
1889  {
1890  itkExceptionMacro( << "fld is NULL" );
1891  return NULL;
1892  }
1893  else
1894  {
1895  if( fld->field_passcount )
1896  {
1897  if( TIFFGetField( m_InternalImage->m_Image, tag, &value_count, &raw_data ) != 1 )
1898  {
1899  itkExceptionMacro( << "Tag cannot be found" );
1900  return NULL;
1901  }
1902  else
1903  {
1904  if( fld->field_type != TIFF_BYTE )
1905  {
1906  itkExceptionMacro( << "Tag is not of type TIFF_BYTE" );
1907  return NULL;
1908  }
1909  }
1910  }
1911  }
1912  return raw_data;
1913 }
1914 
1915 } // end namespace itk

Generated at Sun Feb 3 2013 00:10:02 for Orfeo Toolbox with doxygen 1.8.1.1