Orfeo Toolbox  3.16
itkBMPImageIO.cxx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkBMPImageIO.cxx,v $
5  Language: C++
6  Date: $Date: 2009-10-27 16:05:53 $
7  Version: $Revision: 1.33 $
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 #include "itkBMPImageIO.h"
18 #include "itkExceptionObject.h"
19 #include "itkByteSwapper.h"
20 #include "itkRGBPixel.h"
21 #include "itkRGBAPixel.h"
22 #include <itksys/SystemTools.hxx>
23 #include <iostream>
24 #include <list>
25 #include <string>
26 #include <math.h>
27 
28 namespace itk
29 {
30 
33 {
35  m_BitMapOffset = 0;
36  this->SetNumberOfDimensions(2);
39  m_Spacing[0] = 1.0;
40  m_Spacing[1] = 1.0;
41 
42  m_Origin[0] = 0.0;
43  m_Origin[1] = 0.0;
44  m_FileLowerLeft = 0;
45  m_Depth = 8;
46  m_Allow8BitBMP = false;
47  m_NumberOfColors = 0;
48  m_ColorTableSize = 0;
49  m_BMPCompression = 0;
50  m_BMPDataSize = 0;
51 
52  this->AddSupportedWriteExtension(".bmp");
53  this->AddSupportedWriteExtension(".BMP");
54 
55  this->AddSupportedReadExtension(".bmp");
56  this->AddSupportedReadExtension(".BMP");
57 
58 }
59 
60 
63 {
64 }
65 
66 
67 bool BMPImageIO::CanReadFile( const char* filename )
68 {
69  // First check the filename extension
70  std::string fname = filename;
71  if ( fname == "" )
72  {
73  itkDebugMacro(<< "No filename specified.");
74  }
75 
76  bool extensionFound = false;
77  std::string::size_type BMPPos = fname.rfind(".bmp");
78  if ((BMPPos != std::string::npos)
79  && (BMPPos == fname.length() - 4))
80  {
81  extensionFound = true;
82  }
83 
84  BMPPos = fname.rfind(".BMP");
85  if ((BMPPos != std::string::npos)
86  && (BMPPos == fname.length() - 4))
87  {
88  extensionFound = true;
89  }
90 
91  if( !extensionFound )
92  {
93  itkDebugMacro(<<"The filename extension is not recognized");
94  return false;
95  }
96 
97  // Now check the content
98  std::ifstream inputStream;
99  inputStream.open( filename, std::ios::in | std::ios::binary );
100  if( inputStream.fail() )
101  {
102  return false;
103  }
104 
105  char magic_number1, magic_number2;
106  inputStream.read((char*)&magic_number1,sizeof(char));
107  inputStream.read((char*)&magic_number2,sizeof(char));
108 
109  if ((magic_number1 != 'B')||(magic_number2 != 'M'))
110  {
111  std::cerr << "BMPImageIO : Magic Number Fails = " << magic_number1 << " : " << magic_number2 << std::endl;
112  inputStream.close();
113  return false;
114  }
115 
116  long tmp;
117  long infoSize;
118  int iinfoSize; // in case we are on a 64bit machine
119  int itmp; // in case we are on a 64bit machine
120 
121  // get the size of the file
122  ::size_t sizeLong = sizeof(long);
123  if (sizeLong == 4)
124  {
125  inputStream.read((char*)&tmp,4);
126  // skip 4 bytes
127  inputStream.read((char*)&tmp,4);
128  // read the offset
129  inputStream.read((char*)&tmp,4);
130  }
131  else
132  {
133  inputStream.read((char*)&itmp,4);
134  // skip 4 bytes
135  inputStream.read((char*)&itmp,4);
136  // read the offset
137  inputStream.read((char*)&itmp,4);
138  }
139 
140  // get size of header
141  if (sizeLong == 4) // if we are on a 32 bit machine
142  {
143  inputStream.read((char*)&infoSize,sizeof(long));
145  // error checking
146  if ((infoSize != 40)&&(infoSize != 12))
147  {
148  inputStream.close();
149  return false;
150  }
151  }
152  else // else we are on a 64bit machine
153  {
154  inputStream.read((char*)&iinfoSize,4);
156  infoSize = iinfoSize;
157 
158  // error checking
159  if ((infoSize != 40)&&(infoSize != 12))
160  {
161  inputStream.close();
162  return false;
163  }
164  }
165 
166  inputStream.close();
167  return true;
168 
169 }
170 
171 bool BMPImageIO::CanWriteFile( const char * name )
172 {
173  std::string filename = name;
174  if ( filename == "" )
175  {
176  itkDebugMacro(<< "No filename specified.");
177  }
178 
179  bool extensionFound = false;
180  std::string::size_type BMPPos = filename.rfind(".bmp");
181  if ((BMPPos != std::string::npos)
182  && (BMPPos == filename.length() - 4))
183  {
184  extensionFound = true;
185  }
186 
187  BMPPos = filename.rfind(".BMP");
188  if ((BMPPos != std::string::npos)
189  && (BMPPos == filename.length() - 4))
190  {
191  extensionFound = true;
192  }
193 
194  if( !extensionFound )
195  {
196  itkDebugMacro(<<"The filename extension is not recognized");
197  return false;
198  }
199 
200  if( extensionFound )
201  {
202  return true;
203  }
204  return false;
205 }
206 
207 void BMPImageIO::Read(void* buffer)
208 {
209  char * p = static_cast<char *>(buffer);
210  unsigned long l=0;
211  unsigned long step = this->GetNumberOfComponents();
212  long streamRead = m_Dimensions[0]*m_Depth/8;
213 
214  m_Ifstream.open( m_FileName.c_str(), std::ios::in | std::ios::binary );
215 
216  long paddedStreamRead = streamRead;
217  if( streamRead % 4 )
218  {
219  paddedStreamRead = ( ( streamRead / 4 ) + 1 ) * 4;
220  }
221 
222  char* value = new char[paddedStreamRead+1];
223  if (m_FileLowerLeft)
224  {
225  // If the file is RLE compressed
226  if(m_BMPCompression == 1 && this->GetNumberOfComponents() == 3)
227  {
228  delete [] value;
229  value = new char[m_BMPDataSize+1];
230  m_Ifstream.seekg(m_BitMapOffset,std::ios::beg);
231  m_Ifstream.read((char *)value, m_BMPDataSize);
232 
233  unsigned int posLine=0;
234  unsigned int line = m_Dimensions[1]-1;
235  for(unsigned int i=0;i<m_BMPDataSize;i++)
236  {
237  unsigned long n = value[i];
238  i++;
239  unsigned char valpix = value[i];
240  for(unsigned long j=0;j<n;j++)
241  {
242  RGBPixelType rbg;
243  if(valpix<m_ColorPalette.size())
244  {
245  rbg = m_ColorPalette[valpix];
246  }
247  else
248  {
249  rbg.SetRed(0);
250  rbg.SetGreen(0);
251  rbg.SetBlue(0);
252  }
253  l=3*(line*m_Dimensions[0]+posLine);
254  p[l]=rbg.GetBlue();
255  p[l+1]=rbg.GetGreen();
256  p[l+2]=rbg.GetRed();
257  posLine++;
258  if(posLine == m_Dimensions[0])
259  {
260  line--;
261  posLine=0;
262  }
263  }
264  }
265  }
266  else
267  {
268  // File is not compressed
269  // Read one row at a time
270  for(unsigned int id=0;id<m_Dimensions[1];id++)
271  {
272  m_Ifstream.seekg(m_BitMapOffset + paddedStreamRead*(m_Dimensions[1] - id - 1),std::ios::beg);
273  m_Ifstream.read((char *)value, paddedStreamRead);
274  for(long i=0;i<streamRead;i++)
275  {
276  if(this->GetNumberOfComponents() == 1)
277  {
278  p[l++]=value[i];
279  }
280  else
281  {
282  if(m_ColorTableSize == 0)
283  {
284  if(this->GetNumberOfComponents() == 3 )
285  {
286  p[l++]=value[i+2];
287  p[l++]=value[i+1];
288  p[l++]=value[i];
289  }
290  if(this->GetNumberOfComponents() == 4 )
291  {
292  p[l++]=value[i+3];
293  p[l++]=value[i+2];
294  p[l++]=value[i+1];
295  p[l++]=value[i];
296  }
297  i += step-1;
298  }
299  else
300  {
301  unsigned char val = value[i];
302  RGBPixelType rbg;
303  if(val<m_ColorPalette.size())
304  {
305  rbg = m_ColorPalette[val];
306  }
307  else
308  {
309  rbg.SetRed(0);
310  rbg.SetGreen(0);
311  rbg.SetBlue(0);
312  }
313  p[l++]=rbg.GetBlue();
314  p[l++]=rbg.GetGreen();
315  p[l++]=rbg.GetRed();
316  }
317  }
318  }
319  }
320  }
321  }
322  else
323  // File not lower left
324  {
325  m_Ifstream.seekg(m_BitMapOffset,std::ios::beg);
326  for(unsigned int id=0;id<m_Dimensions[1];id++)
327  {
328  m_Ifstream.read((char *)value, streamRead);
329 
330  for(long i=0;i<streamRead;i+=step)
331  {
332  if(this->GetNumberOfComponents() == 1)
333  {
334  p[l++]=value[i];
335  }
336  else
337  {
338  p[l++]=value[i+2];
339  p[l++]=value[i+1];
340  p[l++]=value[i];
341  }
342  }
343  }
344  }
345  delete []value;
346  m_Ifstream.close();
347 }
348 
354 {
355  int xsize, ysize;
356  long tmp;
357  short stmp;
358  long infoSize;
359  int iinfoSize; // in case we are on a 64bit machine
360  int itmp; // in case we are on a 64bit machine
361 
362  // Now check the content
363  m_Ifstream.open( m_FileName.c_str(), std::ios::in | std::ios::binary );
364  if( m_Ifstream.fail() )
365  {
366  itkExceptionMacro("BMPImageIO could not open file: "
367  << this->GetFileName() << " for reading."
368  << std::endl
369  << "Reason: "
370  << itksys::SystemTools::GetLastSystemError());
371  }
372 
373  char magic_number1, magic_number2;
374  m_Ifstream.read((char*)&magic_number1,sizeof(char));
375  m_Ifstream.read((char*)&magic_number2,sizeof(char));
376 
377  if ((magic_number1 != 'B')||(magic_number2 != 'M'))
378  {
379  m_Ifstream.close();
380  itkExceptionMacro( "BMPImageIO : Magic Number Fails = " << magic_number1 << " : " << magic_number2 );
381  return;
382  }
383 
384  // get the size of the file
385  ::size_t sizeLong = sizeof(long);
386  if (sizeLong == 4)
387  {
388  m_Ifstream.read((char*)&tmp,4);
389  // skip 4 bytes
390  m_Ifstream.read((char*)&tmp,4);
391  // read the offset
392  m_Ifstream.read((char*)&tmp,4);
393  m_BitMapOffset = tmp;
395  }
396  else
397  {
398  m_Ifstream.read((char*)&itmp,4);
399  // skip 4 bytes
400  m_Ifstream.read((char*)&itmp,4);
401  // read the offset
402  m_Ifstream.read((char*)&itmp,4);
404  m_BitMapOffset = static_cast<long>(itmp);
405  }
406 
407  // get size of header
408  if (sizeLong == 4) // if we are on a 32 bit machine
409  {
410  m_Ifstream.read((char*)&infoSize,4);
412  // error checking
413  if ((infoSize != 40)&&(infoSize != 12))
414  {
415  itkExceptionMacro(<<"Unknown file type! " << m_FileName.c_str()
416  <<" is not a Windows BMP file!");
417  m_Ifstream.close();
418  return;
419  }
420 
421  // there are two different types of BMP files
422  if (infoSize == 40)
423  {
424  // now get the dimensions
425  m_Ifstream.read((char*)&xsize,4);
427  m_Ifstream.read((char*)&ysize,4);
429  }
430  else
431  {
432  m_Ifstream.read((char*)&stmp,sizeof(short));
434  xsize = stmp;
435  m_Ifstream.read((char*)&stmp,sizeof(short));
437  ysize = stmp;
438  }
439  }
440  else // else we are on a 64bit machine
441  {
442  m_Ifstream.read((char*)&iinfoSize,sizeof(int));
444 
445  infoSize = iinfoSize;
446 
447  // error checking
448  if ((infoSize != 40)&&(infoSize != 12))
449  {
450  itkExceptionMacro(<<"Unknown file type! " << m_FileName.c_str()
451  <<" is not a Windows BMP file!");
452  m_Ifstream.close();
453  return;
454  }
455 
456  // there are two different types of BMP files
457  if (infoSize == 40)
458  {
459  // now get the dimensions
460  m_Ifstream.read((char*)&xsize,4);
462  m_Ifstream.read((char*)&ysize,4);
464  }
465  else
466  {
467  stmp =0;
468  m_Ifstream.read((char*)&stmp,2);
470  xsize = stmp;
471  m_Ifstream.read((char*)&stmp,2);
473  ysize = stmp;
474  }
475  }
476 
477  this->SetNumberOfDimensions(2);
478  m_Dimensions[0] = xsize;
479  m_Dimensions[1] = ysize;
480 
481  // is corner in upper left or lower left
482  if (ysize < 0)
483  {
484  ysize = ysize*-1;
485  m_FileLowerLeft = 0;
486  }
487  else
488  {
489  m_FileLowerLeft = 1;
490  }
491 
492  // ignore planes
493  m_Ifstream.read((char*)&stmp,2);
494  // read depth
495  m_Ifstream.read((char*)&m_Depth,2);
497 
498  if ((m_Depth != 8)&&(m_Depth != 24)&&(m_Depth != 32))
499  {
500  m_Ifstream.close();
501  itkExceptionMacro( "Only BMP depths of (8,24,32) are supported. Not " << m_Depth );
502  return;
503  }
504 
505  if (infoSize == 40)
506  {
507  if (sizeLong == 4)
508  {
509  // Compression
510  m_Ifstream.read((char*)&m_BMPCompression,4);
512  // Image Data Size
513  m_Ifstream.read((char*)&m_BMPDataSize,4);
515  // Horizontal Resolution
516  m_Ifstream.read((char*)&tmp,4);
517  // Vertical Resolution
518  m_Ifstream.read((char*)&tmp,4);
519  // Number of colors
520  m_Ifstream.read((char*)&tmp,4);
521  m_NumberOfColors = tmp;
522  // Number of important colors
523  m_Ifstream.read((char*)&tmp,4);
524  }
525  else
526  {
527  // Compression
528  m_Ifstream.read((char*)&itmp,4);
530  m_BMPCompression = static_cast<long>(itmp);
531  // Image Data Size
532  m_Ifstream.read((char*)&itmp,4);
534  m_BMPDataSize = static_cast<unsigned long>(itmp);
535  // Horizontal Resolution
536  m_Ifstream.read((char*)&itmp,4);
538  // Vertical Resolution
539  m_Ifstream.read((char*)&itmp,4);
541  // Number of colors
542  m_Ifstream.read((char*)&itmp,4);
544  m_NumberOfColors = static_cast<unsigned short>(itmp);
545  // Number of important colors
546  m_Ifstream.read((char*)&itmp,4);
547  }
548  }
549  // Read the color palette. Only used for 1,4 and 8 bit images.
550  if (m_Depth <= 8)
551  {
552  if (m_NumberOfColors)
553  {
555  }
556  else
557  {
558  m_ColorTableSize = (1 << m_Depth);
559  }
560  }
561  else
562  {
563  m_ColorTableSize = 0;
564  }
565  unsigned char uctmp;
566  for(unsigned long i=0;i<m_ColorTableSize;i++)
567  {
568  RGBPixelType p;
569  m_Ifstream.read((char*)&uctmp,1);
570  p.SetRed(uctmp);
571  m_Ifstream.read((char*)&uctmp,1);
572  p.SetGreen(uctmp);
573  m_Ifstream.read((char*)&uctmp,1);
574  p.SetBlue(uctmp);
575  m_Ifstream.read((char*)&tmp,1);
576  m_ColorPalette.push_back(p);
577  }
578 
579  switch( m_Depth )
580  {
581  case 1:
582  case 4:
583  case 8:
584  {
585  if( m_Allow8BitBMP )
586  {
587  this->SetNumberOfComponents(1);
589  }
590  else
591  {
592  this->SetNumberOfComponents(3);
593  m_PixelType = RGB;
594  }
595  break;
596  }
597  case 24:
598  {
599  this->SetNumberOfComponents(3);
600  m_PixelType = RGB;
601  break;
602  }
603  case 32:
604  {
605  this->SetNumberOfComponents(4);
606  m_PixelType = RGBA;
607  break;
608  }
609  }
610 
611  m_Ifstream.close();
612 }
613 
614 
615 void
617 ::SwapBytesIfNecessary( void* buffer, unsigned long numberOfPixels )
618 {
619  switch(m_ComponentType)
620  {
621  case CHAR:
622  {
623  if ( m_ByteOrder == LittleEndian )
624  {
626  (char*)buffer, numberOfPixels );
627  }
628  else if ( m_ByteOrder == BigEndian )
629  {
631  (char *)buffer, numberOfPixels );
632  }
633  break;
634  }
635  case UCHAR:
636  {
637  if ( m_ByteOrder == LittleEndian )
638  {
640  (unsigned char*)buffer, numberOfPixels );
641  }
642  else if ( m_ByteOrder == BigEndian )
643  {
645  (unsigned char *)buffer, numberOfPixels );
646  }
647  break;
648  }
649  case SHORT:
650  {
651  if ( m_ByteOrder == LittleEndian )
652  {
654  (short*)buffer, numberOfPixels );
655  }
656  else if ( m_ByteOrder == BigEndian )
657  {
659  (short *)buffer, numberOfPixels );
660  }
661  break;
662  }
663  case USHORT:
664  {
665  if ( m_ByteOrder == LittleEndian )
666  {
668  (unsigned short*)buffer, numberOfPixels );
669  }
670  else if ( m_ByteOrder == BigEndian )
671  {
673  (unsigned short *)buffer, numberOfPixels );
674  }
675  break;
676  }
677  default:
678  itkExceptionMacro(<< "Pixel Type Unknown");
679  }
680 }
681 
682 
683 void
685 ::Write32BitsInteger( unsigned int value )
686 {
687  char tmp;
688  tmp = value%256;
689  m_Ofstream.write(&tmp,sizeof(char));
690  tmp = static_cast<char>((value%65536L)/256);
691  m_Ofstream.write(&tmp,sizeof(char));
692  tmp = static_cast<char>((value/65536L)%256);
693  m_Ofstream.write(&tmp,sizeof(char));
694  tmp = static_cast<char>((value/65536L)/256);
695  m_Ofstream.write(&tmp,sizeof(char));
696 }
697 
698 void
700 ::Write16BitsInteger( unsigned short value )
701 {
702  char tmp;
703  tmp = value%256;
704  m_Ofstream.write(&tmp,sizeof(char));
705  tmp = static_cast<char>((value%65536L)/256);
706  m_Ofstream.write(&tmp,sizeof(char));
707 }
708 
709 void
712 {
713 
714 }
715 
717 void
719 ::Write( const void* buffer)
720 {
721 
722  unsigned int nDims = this->GetNumberOfDimensions();
723 
724  if(nDims != 2)
725  {
726  itkExceptionMacro(<< "BMPImageIO cannot write images with a dimension != 2");
727  }
728 
729  if(this->GetComponentType() != UCHAR)
730  {
731  itkExceptionMacro(<<"BMPImageIO supports unsigned char only");
732  }
733  if( (this->m_NumberOfComponents != 1) &&
734  (this->m_NumberOfComponents != 3) &&
735  (this->m_NumberOfComponents != 4) )
736  {
737  itkExceptionMacro(<<"BMPImageIO supports 1,3 or 4 components only");
738  }
739 
740 
741 #ifdef __sgi
742  // Create the file. This is required on some older sgi's
743  std::ofstream tFile(m_FileName.c_str(),std::ios::out);
744  tFile.close();
745 #endif
746 
747  m_Ofstream.open(m_FileName.c_str(), std::ios::binary | std::ios::out);
748  if( m_Ofstream.fail() )
749  {
750  itkExceptionMacro(<< "File: " << this->GetFileName() << " cannot be written."
751  << std::endl
752  << "Reason: "
753  << itksys::SystemTools::GetLastSystemError());
754  }
755 
756  //
757  //
758  // A BMP file has four sections:
759  //
760  // * BMP Header 14 bytes
761  // * Bitmap Information (DIB header) 40 bytes (Windows V3)
762  // * Color Palette
763  // * Bitmap Data
764  //
765  // For more details:
766  //
767  // http://en.wikipedia.org/wiki/BMP_file_format
768  //
769  //
770 
771  // Write the BMP header
772  //
773  // Header structure is represented by first a 14 byte field, then the bitmap
774  // info header.
775  //
776  // The 14 byte field:
777  //
778  // Offset Length Description
779  //
780  // 0 2 Contain the string, "BM", (Hex: 42 4D)
781  // 2 4 The length of the entire file.
782  // 6 2 Reserved for application data. Usually zero.
783  // 8 2 Reserved for application data. Usually zero.
784  // 10 4 Provides an offset from the start of the file
785  // to the first byte of image sample data. This
786  // is normally 54 bytes (Hex: 36)
787  //
788  char tmp = 66;
789  m_Ofstream.write(&tmp,sizeof(char));
790  tmp = 77;
791  m_Ofstream.write(&tmp,sizeof(char));
792 
793  const unsigned int bpp = this->GetNumberOfComponents();
794  long bytesPerRow = m_Dimensions[0]*bpp;
795  if ( bytesPerRow % 4 )
796  {
797  bytesPerRow = ( ( bytesPerRow / 4 ) + 1 ) * 4;
798  }
799  const unsigned long paddedBytes = bytesPerRow - (m_Dimensions[0]*bpp);
800 
801  const unsigned int rawImageDataSize = static_cast<unsigned int>(( bytesPerRow * m_Dimensions[1]));
802  unsigned int fileSize = ( rawImageDataSize ) + 54;
803  if( bpp == 1 )
804  {
805  fileSize += 1024; // need colour LUT
806  }
807  this->Write32BitsInteger( fileSize );
808 
809  const unsigned short applicationReservedValue = 0;
810  this->Write16BitsInteger( applicationReservedValue );
811  this->Write16BitsInteger( applicationReservedValue );
812 
813  unsigned int offsetToBinaryDataStart = 54;
814  if( bpp == 1 ) // more space is needed for the LUT
815  {
816  offsetToBinaryDataStart += 1024;
817  }
818  this->Write32BitsInteger( offsetToBinaryDataStart );
819  //
820  // End of BMP header, 14 bytes written so far
821  //
822 
823 
824  //
825  // Write the DIB header
826  //
827  // Offset Length Description
828  //
829  // 14 4 Size of the header (40 bytes)(Hex: 28)
830  //
831  //
832  // Color Palette
833  //
834  // If the bit_count is 1, 4 or 8, the structure must be followed by a colour
835  // lookup table, with 4 bytes per entry, the first 3 of which identify the
836  // blue, green and red intensities, respectively.
837  //
838  // Finally the pixel data
839  //
840  const unsigned int bitmapHeaderSize = 40;
841  this->Write32BitsInteger( bitmapHeaderSize );
842 
843  // image width
844  this->Write32BitsInteger( m_Dimensions[0] );
845 
846  // image height -ve means top to bottom
847  this->Write32BitsInteger( m_Dimensions[1] );
848 
849  // Set `planes'=1 (mandatory)
850  const unsigned short numberOfColorPlanes = 1;
851  this->Write16BitsInteger( numberOfColorPlanes );
852 
853  // Set bits per pixel.
854  unsigned short numberOfBitsPerPixel = 0;
855  switch( bpp )
856  {
857  case 4:
858  numberOfBitsPerPixel = 32;
859  break;
860  case 3:
861  numberOfBitsPerPixel = 24;
862  break;
863  case 1:
864  numberOfBitsPerPixel = 8;
865  break;
866  default:
867  itkExceptionMacro(<< "Number of components not supported.");
868  }
869  this->Write16BitsInteger( numberOfBitsPerPixel );
870 
871  const unsigned int compressionMethod = 0;
872  this->Write32BitsInteger( compressionMethod );
873  this->Write32BitsInteger( rawImageDataSize );
874 
875  // Assuming spacing is in millimeters,
876  // the resolution is set here in pixel per meter.
877  // The specification calls for a signed integer, but
878  // here we force it to be an unsigned integer to avoid
879  // dealing with directions in a subterraneous way.
880  const unsigned int horizontalResolution = Math::Round<unsigned int>( 1000.0 / m_Spacing[0] );
881  const unsigned int verticalResolution = Math::Round<unsigned int>( 1000.0 / m_Spacing[1] );
882 
883  this->Write32BitsInteger( horizontalResolution );
884  this->Write32BitsInteger( verticalResolution );
885 
886  // zero here defaults to 2^n colors in the palette
887  const unsigned int numberOfColorsInPalette = 0;
888  this->Write32BitsInteger( numberOfColorsInPalette );
889 
890  // zero here indicates that all colors in the palette are important.
891  const unsigned int numberOfImportantColorsInPalette = 0;
892  this->Write32BitsInteger( numberOfImportantColorsInPalette );
893  //
894  // End of DIB header, 54 bytes written so far
895  //
896 
897 
898  //
899  // Write down colour LUT
900  //
901  // only when using 1 byte per pixel
902  //
903  if (bpp == 1)
904  {
905  for (unsigned int n=0; n < 256; n++)
906  {
907  char tmp2 = static_cast< unsigned char >( n );
908  m_Ofstream.write(&tmp2,sizeof(char));
909  m_Ofstream.write(&tmp2,sizeof(char));
910  m_Ofstream.write(&tmp2,sizeof(char));
911  m_Ofstream.write(&tmp,sizeof(char));
912  }
913  }
914 
915 
916  //
917  // Write down the raw binary pixel data
918  //
919  unsigned int i;
920  for (unsigned int h = 0; h < m_Dimensions[1]; h++)
921  {
922  const char paddingValue = 0;
923  const char * ptr = static_cast<const char*>(buffer);
924  ptr += (m_Dimensions[1]-(h+1))*m_Dimensions[0]*bpp;
925  if (bpp == 1)
926  {
927  for (i = 0; i < m_Dimensions[0]; i++)
928  {
929  m_Ofstream.write(ptr,sizeof(char));
930  ptr++;
931  }
932  for (i = 0; i < paddedBytes; i++)
933  {
934  m_Ofstream.write(&paddingValue,sizeof(char));
935  }
936  }
937  if (bpp == 3)
938  {
939  for (i = 0; i < m_Dimensions[0]; i++)
940  {
941  ptr += 2;
942  m_Ofstream.write(ptr,sizeof(char));
943  ptr--;
944  m_Ofstream.write(ptr,sizeof(char));
945  ptr--;
946  m_Ofstream.write(ptr,sizeof(char));
947  ptr += 3;
948  }
949  for (i = 0; i < paddedBytes; i++)
950  {
951  m_Ofstream.write(&paddingValue,sizeof(char));
952  }
953  }
954  if (bpp == 4)
955  {
956  for (i = 0; i < m_Dimensions[0]; i++)
957  {
958  ptr += 3;
959  m_Ofstream.write(ptr,sizeof(char));
960  ptr--;
961  m_Ofstream.write(ptr,sizeof(char));
962  ptr--;
963  m_Ofstream.write(ptr,sizeof(char));
964  ptr--;
965  m_Ofstream.write(ptr,sizeof(char));
966  ptr += 4;
967  }
968  for (i = 0; i < paddedBytes; i++)
969  {
970  m_Ofstream.write(&paddingValue,sizeof(char));
971  }
972  }
973  }
974 }
975 
977 void BMPImageIO::PrintSelf(std::ostream& os, Indent indent) const
978 {
979  Superclass::PrintSelf(os, indent);
980  os << indent << "Depth " << m_Depth << "\n";
981  os << indent << "FileLowerLeft " << m_FileLowerLeft << "\n";
982  os << indent << "BitMapOffset " << m_BitMapOffset << "\n";
983  if(m_Allow8BitBMP)
984  {
985  os << indent << "m_Allow8BitBMP : True" << "\n";
986  }
987  else
988  {
989  os << indent << "m_Allow8BitBMP : False" << "\n";
990  }
991  os << indent << "BMPCompression = " << m_BMPCompression << "\n";
992  os << indent << "DataSize = " << m_BMPDataSize << "\n";
993 }
994 
995 } // end namespace itk

Generated at Sat Feb 2 2013 23:30:23 for Orfeo Toolbox with doxygen 1.8.1.1