ens-ulm-1

google hashcode 2014 source for team ens-ulm-1
git clone https://a3nm.net/git/ens-ulm-1/
Log | Files | Refs

intarray2bmp.hpp (7218B)


      1 // intarray2bmp.hpp
      2 //
      3 // Convert an array of integer values to a bitmap.
      4 // Copyright 2009 Michael Thomas Greer
      5 //
      6 // Boost Software License - Version 1.0 - August 17th, 2003
      7 //
      8 // Permission is hereby granted, free of charge, to any person or organization
      9 // obtaining a copy of the software and accompanying documentation covered by
     10 // this license (the "Software") to use, reproduce, display, distribute,
     11 // execute, and transmit the Software, and to prepare derivative works of the
     12 // Software, and to permit third-parties to whom the Software is furnished to
     13 // do so, all subject to the following:
     14 //
     15 // The copyright notices in the Software and this entire statement, including
     16 // the above license grant, this restriction and the following disclaimer,
     17 // must be included in all copies of the Software, in whole or in part, and
     18 // all derivative works of the Software, unless such copies or derivative
     19 // works are solely in the form of machine-executable object code generated by
     20 // a source language processor.
     21 //
     22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     23 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     24 // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
     25 // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
     26 // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
     27 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     28 // DEALINGS IN THE SOFTWARE.
     29 //
     30 
     31 #ifndef INTARRAY2BMP_HPP
     32 #define INTARRAY2BMP_HPP
     33 
     34 #include <fstream>
     35 #include <iostream>
     36 #include <string>
     37 
     38 namespace intarray2bmp
     39   {
     40 
     41   //-------------------------------------------------------------------------- 
     42   // This little helper is to write little-endian values to file.
     43   //
     44   struct lwrite
     45     {
     46     unsigned long value;
     47     unsigned      size;
     48     lwrite( unsigned long value, unsigned size ):
     49       value( value ), size( size )
     50       { }
     51     };
     52 
     53   //--------------------------------------------------------------------------
     54   inline std::ostream& operator << ( std::ostream& outs, const lwrite& v )
     55     {
     56     unsigned long value = v.value;
     57     for (unsigned cntr = 0; cntr < v.size; cntr++, value >>= 8)
     58       outs.put( static_cast <char> (value & 0xFF) );
     59     return outs;
     60     }
     61 
     62   //--------------------------------------------------------------------------
     63   // Take an integer array and convert it into a color image.
     64   //
     65   // This first version takes an array of array style of array:
     66   //   int* a[ 10 ]
     67   //
     68   // The second, overloaded version takes a flat C-style array:
     69   //   int a[ 10 ][ 10 ]
     70   //
     71   template <typename IntType>
     72   bool intarray2bmp(
     73     const std::string& filename,
     74     IntType**          intarray,
     75     unsigned           rows,
     76     unsigned           columns,
     77     IntType            min_value,
     78     IntType            max_value
     79     ) {
     80     // This is the difference between each color based upon
     81     // the number of distinct values in the input array.
     82     double granularity = 360.0 / ((double)( max_value - min_value ) + 1);
     83 
     84     // Open the output BMP file
     85     std::ofstream f( filename.c_str(),
     86                      std::ios::out | std::ios::trunc | std::ios::binary );
     87     if (!f) return false;
     88 
     89     // Some basic
     90     unsigned long headers_size    = 14  // sizeof( BITMAPFILEHEADER )
     91                                   + 40; // sizeof( BITMAPINFOHEADER )
     92     unsigned long padding_size    = (4 - ((columns * 3) % 4)) % 4;
     93     unsigned long pixel_data_size = rows * ((columns * 3) + padding_size);
     94 
     95     // Write the BITMAPFILEHEADER
     96     f.put( 'B' ).put( 'M' );                           // bfType
     97     f << lwrite( headers_size + pixel_data_size, 4 );  // bfSize
     98     f << lwrite( 0,                              2 );  // bfReserved1
     99     f << lwrite( 0,                              2 );  // bfReserved2
    100     f << lwrite( headers_size,                   4 );  // bfOffBits
    101 
    102     // Write the BITMAPINFOHEADER
    103     f << lwrite( 40,                             4 );  // biSize
    104     f << lwrite( columns,                        4 );  // biWidth
    105     f << lwrite( rows,                           4 );  // biHeight
    106     f << lwrite( 1,                              2 );  // biPlanes
    107     f << lwrite( 24,                             2 );  // biBitCount
    108     f << lwrite( 0,                              4 );  // biCompression=BI_RGB
    109     f << lwrite( pixel_data_size,                4 );  // biSizeImage
    110     f << lwrite( 0,                              4 );  // biXPelsPerMeter
    111     f << lwrite( 0,                              4 );  // biYPelsPerMeter
    112     f << lwrite( 0,                              4 );  // biClrUsed
    113     f << lwrite( 0,                              4 );  // biClrImportant
    114 
    115     // Write the pixel data
    116     for (unsigned row = rows; row; row--)           // bottom-to-top
    117       {
    118       for (unsigned col = 0; col < columns; col++)  // left-to-right
    119         {
    120         unsigned char red, green, blue;
    121         //
    122         // This is how we convert an integer value to a color:
    123         // by mapping it evenly along the CIECAM02 hue color domain.
    124         //
    125         // http://en.wikipedia.org/wiki/Hue
    126         // http://en.wikipedia.org/wiki/hsl_and_hsv#conversion_from_hsv_to_rgb
    127         //
    128         // The following algorithm takes a few shortcuts since
    129         // both 'value' and 'saturation' are always 1.0.
    130         //
    131         double hue = (intarray[ row - 1 ][ col ] - min_value) * granularity;
    132         int    H = (int)( hue / 60 ) % 6;
    133         double F = (hue / 60) - H;
    134         double Q = 1.0 - F;
    135 
    136         #define c( x ) (255 * x)
    137         switch (H)
    138           {
    139           case 0:  red = c(1);  green = c(F);  blue = c(0);  break;
    140           case 1:  red = c(Q);  green = c(1);  blue = c(0);  break;
    141           case 2:  red = c(0);  green = c(1);  blue = c(F);  break;
    142           case 3:  red = c(0);  green = c(Q);  blue = c(1);  break;
    143           case 4:  red = c(F);  green = c(0);  blue = c(1);  break;
    144           default: red = c(1);  green = c(0);  blue = c(Q);
    145           }
    146         #undef c
    147 
    148         f.put( static_cast <char> (blue)  )
    149          .put( static_cast <char> (green) )
    150          .put( static_cast <char> (red)   );
    151         }
    152 
    153       if (padding_size) f << lwrite( 0, padding_size );
    154       }
    155 
    156     // All done!
    157     return f.good();
    158     }
    159 
    160   //--------------------------------------------------------------------------
    161   template <typename IntType>
    162   bool intarray2bmp(
    163     const std::string& filename,
    164     IntType*           intarray,
    165     unsigned           rows,
    166     unsigned           columns,
    167     IntType            min_value,
    168     IntType            max_value
    169     ) {
    170     IntType** ia = new( std::nothrow ) IntType* [ rows ];
    171     for (unsigned row = 0; row < rows; row++)
    172       {
    173       ia[ row ] = intarray + (row * columns);
    174       }
    175     bool result = intarray2bmp(
    176                     filename, ia, rows, columns, min_value, max_value
    177                     );
    178     delete [] ia;
    179     return result;
    180     }
    181 
    182   bool boolarray2bmp(
    183     const std::string& filename,
    184     bool a[ROWS][COLS]
    185     ) {
    186 
    187     return intarray2bmp(filename, (bool*)a, ROWS, COLS, false, true);
    188   }
    189 
    190 
    191   } // namespace intarray2bmp
    192 
    193 #endif
    194 
    195 // end intarray2bmp.hpp