home *** CD-ROM | disk | FTP | other *** search
/ Compressed Image File Formats / CompressedImageFileFormatsJohnMiano.iso / pc / Library / source / bmpencod.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-17  |  6.0 KB  |  235 lines

  1. //
  2. // Copyright (c) 1997,1998 Colosseum Builders, Inc.
  3. // All rights reserved.
  4. //
  5. // Colosseum Builders, Inc. makes no warranty, expressed or implied
  6. // with regards to this software. It is provided as is.
  7. //
  8. // See the README.TXT file that came with this software for restrictions
  9. // on the use and redistribution of this file or send E-mail to
  10. // info@colosseumbuilders.com
  11. //
  12.  
  13. //
  14. // Title:  Windows Bitmap Coder
  15. //
  16. // Author: John M. Miano miano@colosseumbuilders.com
  17. //
  18.  
  19. #include <windows.h>
  20.  
  21. #include "bmpencod.h"
  22.  
  23. const UBYTE2 Signature = 'B'|('M'<<8) ;
  24.  
  25. //
  26. //  Description:
  27. //
  28. //    Default class constructor
  29. //
  30. BmpEncoder::BmpEncoder ()
  31. {
  32.   Initialize () ;
  33.   return ;
  34. }
  35.  
  36. //
  37. //  Description:
  38. //
  39. //    Class copy constructor
  40. //
  41. BmpEncoder::BmpEncoder (const BmpEncoder &source)
  42. {
  43.   Initialize () ;
  44.   DoCopy (source) ;
  45.   return ;
  46. }
  47.  
  48. //
  49. //  Descriptor:
  50. //
  51. //    Class destructor
  52. //
  53. BmpEncoder::~BmpEncoder ()
  54. {
  55.   return ;
  56. }
  57.  
  58. //
  59. //  Description:
  60. //
  61. //    Class assignment operator.
  62. //
  63. //  Parameters:
  64. //    source:  The object to copy
  65. //
  66. BmpEncoder &BmpEncoder::operator=(const BmpEncoder &source)
  67. {
  68.   DoCopy (source) ;
  69.   return *this ;
  70. }
  71.  
  72. //
  73. //  Description:
  74. //
  75. //    Common object initialization
  76. //
  77. void BmpEncoder::Initialize ()
  78. {
  79.   // For now, a NoOp.
  80.   return ;
  81. }
  82.  
  83. //
  84. //  Description:
  85. //
  86. //    Common object copy function.
  87. //
  88. //  Parameters:
  89. //    source:  The object to copy
  90. //
  91. void BmpEncoder::DoCopy (const BmpEncoder &source)
  92. {
  93.   BitmapImageEncoder::DoCopy (source) ;
  94.   return ;
  95. }
  96.  
  97. //
  98. //  Description:
  99. //
  100. //    This function writes an image to a BMP stream.
  101. //
  102. //  Parameters:
  103. //    strm:  The output stream
  104. //    image:  The image to output
  105. //
  106. void BmpEncoder::WriteImage (std::ostream &strm, BitmapImage &image)
  107. {
  108.   // We need this because MSVC++ does not follow standard scoping rules
  109.   // in for statements
  110.   unsigned int ii ;
  111.  
  112.   switch (image.BitCount ())
  113.   {
  114.   case 1: case 4: case 8: case 24:
  115.     break ;
  116.   default:
  117.     throw EBmpNotSupported () ;
  118.   }
  119.  
  120.   BITMAPFILEHEADER fileheader = {
  121.           SystemToLittleEndian (Signature),
  122.           0,
  123.           0,
  124.           0,
  125.           0 } ;
  126.   BITMAPINFOHEADER infoheader = {
  127.           SystemToLittleEndian ((UBYTE4)sizeof (BITMAPINFOHEADER)),
  128.           SystemToLittleEndian ((UBYTE4)image.Width ()),
  129.           SystemToLittleEndian ((UBYTE4)image.Height ()),
  130.           SystemToLittleEndian ((UBYTE2) 1), // Planes
  131.           0,                // biBitCount
  132.           SystemToLittleEndian ((UBYTE4) BI_RGB), // biCompression
  133.           0,                // biXPelsPerMeter
  134.           0,                // biYPelsPerMeter
  135.           0,                // biClrUsed
  136.           0,                // biClrImportant
  137.           } ;
  138.   unsigned int colorsize = sizeof (RGBQUAD)
  139.                            * image.ColorCount () ;
  140.  
  141.   // Determine the amount of space required to store each
  142.   // row of the image.
  143.   unsigned int outputwidth ;
  144.   if (image.BitCount () != 24)
  145.   {
  146.     unsigned int bitwidth = image.BitCount () * image.Width () ;
  147.     outputwidth = (bitwidth + 7)/8 ;
  148.   }
  149.   else
  150.   {
  151.     outputwidth = sizeof (RGBTRIPLE) * image.Width () ;
  152.   }
  153.  
  154.   // Find the amount of space required to pad the output rows to
  155.   // a multiple of four bytes.
  156.   unsigned int padsize = ((outputwidth + 0x3) & ~0x3) - outputwidth ;
  157.  
  158.   // Calulate the space required for the image.
  159.   unsigned int datasize = image.Height () * (outputwidth + padsize) ;
  160.   unsigned int spacerequired = sizeof (BITMAPFILEHEADER)
  161.                              + sizeof (BITMAPINFOHEADER)
  162.                              + colorsize + datasize ;
  163.  
  164.   // Fill in the remaining header fields.
  165.   fileheader.bfOffBits = SystemToLittleEndian ((UBYTE4)sizeof (BITMAPFILEHEADER)
  166.                          + sizeof (BITMAPINFOHEADER)
  167.                          + colorsize) ;
  168.   fileheader.bfSize = SystemToLittleEndian ((UBYTE4) spacerequired) ;
  169.   infoheader.biBitCount = SystemToLittleEndian ((UBYTE2) image.BitCount ()) ;
  170.   // Write the header.
  171.   strm.write ((char *) &fileheader, sizeof (BITMAPFILEHEADER)) ;
  172.   strm.write ((char *) &infoheader, sizeof (BITMAPINFOHEADER)) ;
  173.  
  174.   for (ii = 0 ; ii < image.ColorCount () ; ++ ii)
  175.   {
  176.     RGBQUAD data ;
  177.     data.rgbRed = image.ColorMap (ii).red ;
  178.     data.rgbGreen = image.ColorMap (ii).green ;
  179.     data.rgbBlue = image.ColorMap (ii).blue ;
  180.     data.rgbReserved = 0 ;
  181.     strm.write ((char *) &data, sizeof (RGBQUAD)) ;
  182.   }
  183.  
  184.   CallProgressFunction (0) ;
  185.   if (image.BitCount () != 24)
  186.   {
  187.     for (ii = 0 ; ii < image.Height () ; ++ ii)
  188.     {
  189.       CallProgressFunction (ii * 100 /image.Height ()) ;
  190.       static const char pad [4] = { 0, 0, 0, 0, } ;
  191.       unsigned int index = image.Height () - ii - 1 ;
  192.       strm.write ((char* ) &image [index][0], outputwidth) ;
  193.       strm.write (pad, padsize) ;
  194.     }
  195.   }
  196.   else
  197.   {
  198.     for (ii = 0 ; ii < image.Height () ; ++ ii)
  199.     {
  200.       CallProgressFunction (ii * 100 /image.Height ()) ;
  201.       unsigned int index = image.Height () - ii - 1 ;
  202.       for (unsigned int ii = 0 ; ii < 3 * image.Width () ; ii += 3)
  203.       {
  204.         // Remember BMP puts the colors in reverse order BGR.
  205.         strm.write ((char *) &image [index][ii+BitmapImage::BlueOffset], 1) ;
  206.         strm.write ((char *) &image [index][ii+BitmapImage::GreenOffset], 1) ;
  207.         strm.write ((char *) &image [index][ii+BitmapImage::RedOffset], 1) ;
  208.       }
  209.       static const char pad [4] = { 0, 0, 0, 0, } ;
  210.       strm.write (pad, padsize) ;
  211.     }
  212.   }
  213.   CallProgressFunction (100) ;
  214.   return ;
  215. }
  216.  
  217. //
  218. //  Description:
  219. //
  220. //    This function calls the progress function if it has been defined.
  221. //
  222. //  Parameters:
  223. //    percent: The percent completed (0..100)
  224. //    
  225. void BmpEncoder::CallProgressFunction (unsigned int percent)
  226. {
  227.   if (progress_function == NULL)
  228.     return ;
  229.   bool cancel = false ;
  230.   progress_function (*this, progress_data, 1, 1, percent, cancel) ;
  231.   if (cancel)
  232.     throw EGraphicsAbort () ;
  233.   return ;
  234.  }
  235.