Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                           License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
     14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
     15 // Third party copyrights are property of their respective owners.
     16 //
     17 // Redistribution and use in source and binary forms, with or without modification,
     18 // are permitted provided that the following conditions are met:
     19 //
     20 //   * Redistribution's of source code must retain the above copyright notice,
     21 //     this list of conditions and the following disclaimer.
     22 //
     23 //   * Redistribution's in binary form must reproduce the above copyright notice,
     24 //     this list of conditions and the following disclaimer in the documentation
     25 //     and/or other materials provided with the distribution.
     26 //
     27 //   * The name of the copyright holders may not be used to endorse or promote products
     28 //     derived from this software without specific prior written permission.
     29 //
     30 // This software is provided by the copyright holders and contributors "as is" and
     31 // any express or implied warranties, including, but not limited to, the implied
     32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     33 // In no event shall the Intel Corporation or contributors be liable for any direct,
     34 // indirect, incidental, special, exemplary, or consequential damages
     35 // (including, but not limited to, procurement of substitute goods or services;
     36 // loss of use, data, or profits; or business interruption) however caused
     37 // and on any theory of liability, whether in contract, strict liability,
     38 // or tort (including negligence or otherwise) arising in any way out of
     39 // the use of this software, even if advised of the possibility of such damage.
     40 //
     41 //M*/
     42 
     43 #include "precomp.hpp"
     44 
     45 #ifdef HAVE_OPENEXR
     46 
     47 #if defined _MSC_VER && _MSC_VER >= 1200
     48 #  pragma warning( disable: 4100 4244 4267 )
     49 #endif
     50 
     51 #if defined __GNUC__ && defined __APPLE__
     52 #  pragma GCC diagnostic ignored "-Wshadow"
     53 #endif
     54 
     55 #include <ImfHeader.h>
     56 #include <ImfInputFile.h>
     57 #include <ImfOutputFile.h>
     58 #include <ImfChannelList.h>
     59 #include <ImfStandardAttributes.h>
     60 #include <half.h>
     61 #include "grfmt_exr.hpp"
     62 
     63 #if defined _WIN32
     64 
     65 #undef UINT
     66 #define UINT ((Imf::PixelType)0)
     67 #undef HALF
     68 #define HALF ((Imf::PixelType)1)
     69 #undef FLOAT
     70 #define FLOAT ((Imf::PixelType)2)
     71 
     72 #endif
     73 
     74 namespace cv
     75 {
     76 
     77 /////////////////////// ExrDecoder ///////////////////
     78 
     79 ExrDecoder::ExrDecoder()
     80 {
     81     m_signature = "\x76\x2f\x31\x01";
     82     m_file = 0;
     83     m_red = m_green = m_blue = 0;
     84 }
     85 
     86 
     87 ExrDecoder::~ExrDecoder()
     88 {
     89     close();
     90 }
     91 
     92 
     93 void  ExrDecoder::close()
     94 {
     95     if( m_file )
     96     {
     97         delete m_file;
     98         m_file = 0;
     99     }
    100 }
    101 
    102 
    103 int  ExrDecoder::type() const
    104 {
    105     return CV_MAKETYPE((m_isfloat ? CV_32F : CV_32S), m_iscolor ? 3 : 1);
    106 }
    107 
    108 
    109 bool  ExrDecoder::readHeader()
    110 {
    111     bool result = false;
    112 
    113     m_file = new InputFile( m_filename.c_str() );
    114 
    115     if( !m_file ) // probably paranoid
    116         return false;
    117 
    118     m_datawindow = m_file->header().dataWindow();
    119     m_width = m_datawindow.max.x - m_datawindow.min.x + 1;
    120     m_height = m_datawindow.max.y - m_datawindow.min.y + 1;
    121 
    122     // the type HALF is converted to 32 bit float
    123     // and the other types supported by OpenEXR are 32 bit anyway
    124     m_bit_depth = 32;
    125 
    126     if( hasChromaticities( m_file->header() ))
    127         m_chroma = chromaticities( m_file->header() );
    128 
    129     const ChannelList &channels = m_file->header().channels();
    130     m_red = channels.findChannel( "R" );
    131     m_green = channels.findChannel( "G" );
    132     m_blue = channels.findChannel( "B" );
    133     if( m_red || m_green || m_blue )
    134     {
    135         m_iscolor = true;
    136         m_ischroma = false;
    137         result = true;
    138     }
    139     else
    140     {
    141         m_green = channels.findChannel( "Y" );
    142         if( m_green )
    143         {
    144             m_ischroma = true;
    145             m_red = channels.findChannel( "RY" );
    146             m_blue = channels.findChannel( "BY" );
    147             m_iscolor = (m_blue || m_red);
    148             result = true;
    149         }
    150         else
    151             result = false;
    152     }
    153 
    154     if( result )
    155     {
    156         int uintcnt = 0;
    157         int chcnt = 0;
    158         if( m_red )
    159         {
    160             chcnt++;
    161             uintcnt += ( m_red->type == UINT );
    162         }
    163         if( m_green )
    164         {
    165             chcnt++;
    166             uintcnt += ( m_green->type == UINT );
    167         }
    168         if( m_blue )
    169         {
    170             chcnt++;
    171             uintcnt += ( m_blue->type == UINT );
    172         }
    173         m_type = (chcnt == uintcnt) ? UINT : FLOAT;
    174 
    175         m_isfloat = (m_type == FLOAT);
    176     }
    177 
    178     if( !result )
    179         close();
    180 
    181     return result;
    182 }
    183 
    184 
    185 bool  ExrDecoder::readData( Mat& img )
    186 {
    187     m_native_depth = CV_MAT_DEPTH(type()) == img.depth();
    188     bool color = img.channels() > 1;
    189 
    190     uchar* data = img.ptr();
    191     int step = img.step;
    192     bool justcopy = m_native_depth;
    193     bool chromatorgb = false;
    194     bool rgbtogray = false;
    195     bool result = true;
    196     FrameBuffer frame;
    197     int xsample[3] = {1, 1, 1};
    198     char *buffer;
    199     int xstep;
    200     int ystep;
    201 
    202     xstep = m_native_depth ? 4 : 1;
    203 
    204     if( !m_native_depth || (!color && m_iscolor ))
    205     {
    206         buffer = (char *)new float[ m_width * 3 ];
    207         ystep = 0;
    208     }
    209     else
    210     {
    211         buffer = (char *)data;
    212         ystep = step;
    213     }
    214 
    215     if( m_ischroma )
    216     {
    217         if( color )
    218         {
    219             if( m_iscolor )
    220             {
    221                 if( m_blue )
    222                 {
    223                     frame.insert( "BY", Slice( m_type,
    224                                     buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep,
    225                                     12, ystep, m_blue->xSampling, m_blue->ySampling, 0.0 ));
    226                     xsample[0] = m_blue->ySampling;
    227                 }
    228                 if( m_green )
    229                 {
    230                     frame.insert( "Y", Slice( m_type,
    231                                     buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 4,
    232                                     12, ystep, m_green->xSampling, m_green->ySampling, 0.0 ));
    233                     xsample[1] = m_green->ySampling;
    234                 }
    235                 if( m_red )
    236                 {
    237                     frame.insert( "RY", Slice( m_type,
    238                                     buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 8,
    239                                     12, ystep, m_red->xSampling, m_red->ySampling, 0.0 ));
    240                     xsample[2] = m_red->ySampling;
    241                 }
    242                 chromatorgb = true;
    243             }
    244             else
    245             {
    246                 frame.insert( "Y", Slice( m_type,
    247                               buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep,
    248                               12, ystep, m_green->xSampling, m_green->ySampling, 0.0 ));
    249                 frame.insert( "Y", Slice( m_type,
    250                               buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 4,
    251                               12, ystep, m_green->xSampling, m_green->ySampling, 0.0 ));
    252                 frame.insert( "Y", Slice( m_type,
    253                               buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 8,
    254                               12, ystep, m_green->xSampling, m_green->ySampling, 0.0 ));
    255                 xsample[0] = m_green->ySampling;
    256                 xsample[1] = m_green->ySampling;
    257                 xsample[2] = m_green->ySampling;
    258             }
    259         }
    260         else
    261         {
    262             frame.insert( "Y", Slice( m_type,
    263                             buffer - m_datawindow.min.x * 4 - m_datawindow.min.y * ystep,
    264                             4, ystep, m_green->xSampling, m_green->ySampling, 0.0 ));
    265             xsample[0] = m_green->ySampling;
    266         }
    267     }
    268     else
    269     {
    270         if( m_blue )
    271         {
    272             frame.insert( "B", Slice( m_type,
    273                             buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep,
    274                             12, ystep, m_blue->xSampling, m_blue->ySampling, 0.0 ));
    275             xsample[0] = m_blue->ySampling;
    276         }
    277         if( m_green )
    278         {
    279             frame.insert( "G", Slice( m_type,
    280                             buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 4,
    281                             12, ystep, m_green->xSampling, m_green->ySampling, 0.0 ));
    282             xsample[1] = m_green->ySampling;
    283         }
    284         if( m_red )
    285         {
    286             frame.insert( "R", Slice( m_type,
    287                             buffer - m_datawindow.min.x * 12 - m_datawindow.min.y * ystep + 8,
    288                             12, ystep, m_red->xSampling, m_red->ySampling, 0.0 ));
    289             xsample[2] = m_red->ySampling;
    290         }
    291         if(color == 0)
    292         {
    293             rgbtogray = true;
    294             justcopy = false;
    295         }
    296     }
    297 
    298     m_file->setFrameBuffer( frame );
    299     if( justcopy )
    300     {
    301         m_file->readPixels( m_datawindow.min.y, m_datawindow.max.y );
    302 
    303         if( color )
    304         {
    305             if( m_blue && (m_blue->xSampling != 1 || m_blue->ySampling != 1) )
    306                 UpSample( data, 3, step / xstep, xsample[0], m_blue->ySampling );
    307             if( m_green && (m_green->xSampling != 1 || m_green->ySampling != 1) )
    308                 UpSample( data + xstep, 3, step / xstep, xsample[1], m_green->ySampling );
    309             if( m_red && (m_red->xSampling != 1 || m_red->ySampling != 1) )
    310                 UpSample( data + 2 * xstep, 3, step / xstep, xsample[2], m_red->ySampling );
    311         }
    312         else if( m_green && (m_green->xSampling != 1 || m_green->ySampling != 1) )
    313             UpSample( data, 1, step / xstep, xsample[0], m_green->ySampling );
    314     }
    315     else
    316     {
    317         uchar *out = data;
    318         int x, y;
    319         for( y = m_datawindow.min.y; y <= m_datawindow.max.y; y++ )
    320         {
    321             m_file->readPixels( y, y );
    322 
    323             if( rgbtogray )
    324             {
    325                 if( xsample[0] != 1 )
    326                     UpSampleX( (float *)buffer, 3, xsample[0] );
    327                 if( xsample[1] != 1 )
    328                     UpSampleX( (float *)buffer + 4, 3, xsample[1] );
    329                 if( xsample[2] != 1 )
    330                     UpSampleX( (float *)buffer + 8, 3, xsample[2] );
    331 
    332                 RGBToGray( (float *)buffer, (float *)out );
    333             }
    334             else
    335             {
    336                 if( xsample[0] != 1 )
    337                     UpSampleX( (float *)buffer, 3, xsample[0] );
    338                 if( xsample[1] != 1 )
    339                     UpSampleX( (float *)(buffer + 4), 3, xsample[1] );
    340                 if( xsample[2] != 1 )
    341                     UpSampleX( (float *)(buffer + 8), 3, xsample[2] );
    342 
    343                 if( chromatorgb )
    344                     ChromaToBGR( (float *)buffer, 1, step );
    345 
    346                 if( m_type == FLOAT )
    347                 {
    348                     float *fi = (float *)buffer;
    349                     for( x = 0; x < m_width * 3; x++)
    350                     {
    351                         out[x] = cv::saturate_cast<uchar>(fi[x]*5);
    352                     }
    353                 }
    354                 else
    355                 {
    356                     unsigned *ui = (unsigned *)buffer;
    357                     for( x = 0; x < m_width * 3; x++)
    358                     {
    359                         out[x] = cv::saturate_cast<uchar>(ui[x]);
    360                     }
    361                 }
    362             }
    363 
    364             out += step;
    365         }
    366         if( color )
    367         {
    368             if( m_blue && (m_blue->xSampling != 1 || m_blue->ySampling != 1) )
    369                 UpSampleY( data, 3, step / xstep, m_blue->ySampling );
    370             if( m_green && (m_green->xSampling != 1 || m_green->ySampling != 1) )
    371                 UpSampleY( data + xstep, 3, step / xstep, m_green->ySampling );
    372             if( m_red && (m_red->xSampling != 1 || m_red->ySampling != 1) )
    373                 UpSampleY( data + 2 * xstep, 3, step / xstep, m_red->ySampling );
    374         }
    375         else if( m_green && (m_green->xSampling != 1 || m_green->ySampling != 1) )
    376             UpSampleY( data, 1, step / xstep, m_green->ySampling );
    377     }
    378 
    379     if( chromatorgb )
    380         ChromaToBGR( (float *)data, m_height, step / xstep );
    381 
    382     close();
    383 
    384     return result;
    385 }
    386 
    387 /**
    388 // on entry pixel values are stored packed in the upper left corner of the image
    389 // this functions expands them by duplication to cover the whole image
    390  */
    391 void  ExrDecoder::UpSample( uchar *data, int xstep, int ystep, int xsample, int ysample )
    392 {
    393     for( int y = (m_height - 1) / ysample, yre = m_height - ysample; y >= 0; y--, yre -= ysample )
    394     {
    395         for( int x = (m_width - 1) / xsample, xre = m_width - xsample; x >= 0; x--, xre -= xsample )
    396         {
    397             for( int i = 0; i < ysample; i++ )
    398             {
    399                 for( int n = 0; n < xsample; n++ )
    400                 {
    401                     if( !m_native_depth )
    402                         data[(yre + i) * ystep + (xre + n) * xstep] = data[y * ystep + x * xstep];
    403                     else if( m_type == FLOAT )
    404                         ((float *)data)[(yre + i) * ystep + (xre + n) * xstep] = ((float *)data)[y * ystep + x * xstep];
    405                     else
    406                         ((unsigned *)data)[(yre + i) * ystep + (xre + n) * xstep] = ((unsigned *)data)[y * ystep + x * xstep];
    407                 }
    408             }
    409         }
    410     }
    411 }
    412 
    413 /**
    414 // on entry pixel values are stored packed in the upper left corner of the image
    415 // this functions expands them by duplication to cover the whole image
    416  */
    417 void  ExrDecoder::UpSampleX( float *data, int xstep, int xsample )
    418 {
    419     for( int x = (m_width - 1) / xsample, xre = m_width - xsample; x >= 0; x--, xre -= xsample )
    420     {
    421         for( int n = 0; n < xsample; n++ )
    422         {
    423             if( m_type == FLOAT )
    424                 ((float *)data)[(xre + n) * xstep] = ((float *)data)[x * xstep];
    425             else
    426                 ((unsigned *)data)[(xre + n) * xstep] = ((unsigned *)data)[x * xstep];
    427         }
    428     }
    429 }
    430 
    431 /**
    432 // on entry pixel values are stored packed in the upper left corner of the image
    433 // this functions expands them by duplication to cover the whole image
    434  */
    435 void  ExrDecoder::UpSampleY( uchar *data, int xstep, int ystep, int ysample )
    436 {
    437     for( int y = m_height - ysample, yre = m_height - ysample; y >= 0; y -= ysample, yre -= ysample )
    438     {
    439         for( int x = 0; x < m_width; x++ )
    440         {
    441             for( int i = 1; i < ysample; i++ )
    442             {
    443                 if( !m_native_depth )
    444                     data[(yre + i) * ystep + x * xstep] = data[y * ystep + x * xstep];
    445                 else if( m_type == FLOAT )
    446                     ((float *)data)[(yre + i) * ystep + x * xstep] = ((float *)data)[y * ystep + x * xstep];
    447                 else
    448                     ((unsigned *)data)[(yre + i) * ystep + x * xstep] = ((unsigned *)data)[y * ystep + x * xstep];
    449             }
    450         }
    451     }
    452 }
    453 
    454 /**
    455 // algorithm from ImfRgbaYca.cpp
    456  */
    457 void  ExrDecoder::ChromaToBGR( float *data, int numlines, int step )
    458 {
    459     for( int y = 0; y < numlines; y++ )
    460     {
    461         for( int x = 0; x < m_width; x++ )
    462         {
    463             double b, Y, r;
    464             if( !m_native_depth )
    465             {
    466                 b = ((uchar *)data)[y * step + x * 3];
    467                 Y = ((uchar *)data)[y * step + x * 3 + 1];
    468                 r = ((uchar *)data)[y * step + x * 3 + 2];
    469             }
    470             else if( m_type == FLOAT )
    471             {
    472                 b = data[y * step + x * 3];
    473                 Y = data[y * step + x * 3 + 1];
    474                 r = data[y * step + x * 3 + 2];
    475             }
    476             else
    477             {
    478                 b = ((unsigned *)data)[y * step + x * 3];
    479                 Y = ((unsigned *)data)[y * step + x * 3 + 1];
    480                 r = ((unsigned *)data)[y * step + x * 3 + 2];
    481             }
    482             r = (r + 1) * Y;
    483             b = (b + 1) * Y;
    484             Y = (Y - b * m_chroma.blue[1] - r * m_chroma.red[1]) / m_chroma.green[1];
    485 
    486             if( !m_native_depth )
    487             {
    488                 ((uchar *)data)[y * step + x * 3 + 0] = cv::saturate_cast<uchar>(b);
    489                 ((uchar *)data)[y * step + x * 3 + 1] = cv::saturate_cast<uchar>(Y);
    490                 ((uchar *)data)[y * step + x * 3 + 2] = cv::saturate_cast<uchar>(r);
    491             }
    492             else if( m_type == FLOAT )
    493             {
    494                 data[y * step + x * 3] = (float)b;
    495                 data[y * step + x * 3 + 1] = (float)Y;
    496                 data[y * step + x * 3 + 2] = (float)r;
    497             }
    498             else
    499             {
    500                 int t = cvRound(b);
    501                 ((unsigned *)data)[y * step + x * 3 + 0] = (unsigned)MAX(t, 0);
    502                 t = cvRound(Y);
    503                 ((unsigned *)data)[y * step + x * 3 + 1] = (unsigned)MAX(t, 0);
    504                 t = cvRound(r);
    505                 ((unsigned *)data)[y * step + x * 3 + 2] = (unsigned)MAX(t, 0);
    506             }
    507         }
    508     }
    509 }
    510 
    511 
    512 /**
    513 // convert one row to gray
    514 */
    515 void  ExrDecoder::RGBToGray( float *in, float *out )
    516 {
    517     if( m_type == FLOAT )
    518     {
    519         if( m_native_depth )
    520         {
    521             for( int i = 0, n = 0; i < m_width; i++, n += 3 )
    522                 out[i] = in[n] * m_chroma.blue[0] + in[n + 1] * m_chroma.green[0] + in[n + 2] * m_chroma.red[0];
    523         }
    524         else
    525         {
    526             uchar *o = (uchar *)out;
    527             for( int i = 0, n = 0; i < m_width; i++, n += 3 )
    528                 o[i] = (uchar) (in[n] * m_chroma.blue[0] + in[n + 1] * m_chroma.green[0] + in[n + 2] * m_chroma.red[0]);
    529         }
    530     }
    531     else // UINT
    532     {
    533         if( m_native_depth )
    534         {
    535             unsigned *ui = (unsigned *)in;
    536             for( int i = 0; i < m_width * 3; i++ )
    537                 ui[i] -= 0x80000000;
    538             int *si = (int *)in;
    539             for( int i = 0, n = 0; i < m_width; i++, n += 3 )
    540                 ((int *)out)[i] = int(si[n] * m_chroma.blue[0] + si[n + 1] * m_chroma.green[0] + si[n + 2] * m_chroma.red[0]);
    541         }
    542         else // how to best convert float to uchar?
    543         {
    544             unsigned *ui = (unsigned *)in;
    545             for( int i = 0, n = 0; i < m_width; i++, n += 3 )
    546                 ((uchar *)out)[i] = uchar((ui[n] * m_chroma.blue[0] + ui[n + 1] * m_chroma.green[0] + ui[n + 2] * m_chroma.red[0]) * (256.0 / 4294967296.0));
    547         }
    548     }
    549 }
    550 
    551 
    552 ImageDecoder ExrDecoder::newDecoder() const
    553 {
    554     return makePtr<ExrDecoder>();
    555 }
    556 
    557 /////////////////////// ExrEncoder ///////////////////
    558 
    559 
    560 ExrEncoder::ExrEncoder()
    561 {
    562     m_description = "OpenEXR Image files (*.exr)";
    563 }
    564 
    565 
    566 ExrEncoder::~ExrEncoder()
    567 {
    568 }
    569 
    570 
    571 bool  ExrEncoder::isFormatSupported( int depth ) const
    572 {
    573     return CV_MAT_DEPTH(depth) >= CV_8U && CV_MAT_DEPTH(depth) < CV_64F;
    574 }
    575 
    576 
    577 // TODO scale appropriately
    578 bool  ExrEncoder::write( const Mat& img, const std::vector<int>& )
    579 {
    580     int width = img.cols, height = img.rows;
    581     int depth = img.depth(), channels = img.channels();
    582     bool result = false;
    583     bool issigned = depth == CV_8S || depth == CV_16S || depth == CV_32S;
    584     bool isfloat = depth == CV_32F || depth == CV_64F;
    585     depth = CV_ELEM_SIZE1(depth)*8;
    586     const int step = img.step;
    587 
    588     Header header( width, height );
    589     Imf::PixelType type;
    590 
    591     if(depth == 8)
    592         type = HALF;
    593     else if(isfloat)
    594         type = FLOAT;
    595     else
    596         type = UINT;
    597 
    598     if( channels == 3 )
    599     {
    600         header.channels().insert( "R", Channel( type ));
    601         header.channels().insert( "G", Channel( type ));
    602         header.channels().insert( "B", Channel( type ));
    603         //printf("bunt\n");
    604     }
    605     else
    606     {
    607         header.channels().insert( "Y", Channel( type ));
    608         //printf("gray\n");
    609     }
    610 
    611     OutputFile file( m_filename.c_str(), header );
    612 
    613     FrameBuffer frame;
    614 
    615     char *buffer;
    616     int bufferstep;
    617     int size;
    618     if( type == FLOAT && depth == 32 )
    619     {
    620         buffer = (char *)const_cast<uchar *>(img.ptr());
    621         bufferstep = step;
    622         size = 4;
    623     }
    624     else if( depth > 16 || type == UINT )
    625     {
    626         buffer = (char *)new unsigned[width * channels];
    627         bufferstep = 0;
    628         size = 4;
    629     }
    630     else
    631     {
    632         buffer = (char *)new half[width * channels];
    633         bufferstep = 0;
    634         size = 2;
    635     }
    636 
    637     //printf("depth %d %s\n", depth, types[type]);
    638 
    639     if( channels == 3 )
    640     {
    641         frame.insert( "B", Slice( type, buffer, size * 3, bufferstep ));
    642         frame.insert( "G", Slice( type, buffer + size, size * 3, bufferstep ));
    643         frame.insert( "R", Slice( type, buffer + size * 2, size * 3, bufferstep ));
    644     }
    645     else
    646         frame.insert( "Y", Slice( type, buffer, size, bufferstep ));
    647 
    648     file.setFrameBuffer( frame );
    649 
    650     int offset = issigned ? 1 << (depth - 1) : 0;
    651 
    652     result = true;
    653     if( type == FLOAT && depth == 32 )
    654     {
    655         try
    656         {
    657             file.writePixels( height );
    658         }
    659         catch(...)
    660         {
    661             result = false;
    662         }
    663     }
    664     else
    665     {
    666     //    int scale = 1 << (32 - depth);
    667     //    printf("scale %d\n", scale);
    668         for(int line = 0; line < height; line++)
    669         {
    670             if(type == UINT)
    671             {
    672                 unsigned *buf = (unsigned*)buffer; // FIXME 64-bit problems
    673 
    674                 if( depth <= 8 )
    675                 {
    676                     const uchar* sd = img.ptr(line);
    677                     for(int i = 0; i < width * channels; i++)
    678                         buf[i] = sd[i] + offset;
    679                 }
    680                 else if( depth <= 16 )
    681                 {
    682                     const unsigned short *sd = img.ptr<unsigned short>(line);
    683                     for(int i = 0; i < width * channels; i++)
    684                         buf[i] = sd[i] + offset;
    685                 }
    686                 else
    687                 {
    688                     const int *sd = img.ptr<int>(line); // FIXME 64-bit problems
    689                     for(int i = 0; i < width * channels; i++)
    690                         buf[i] = (unsigned) sd[i] + offset;
    691                 }
    692             }
    693             else
    694             {
    695                 half *buf = (half *)buffer;
    696 
    697                 if( depth <= 8 )
    698                 {
    699                     const uchar* sd = img.ptr(line);
    700                     for(int i = 0; i < width * channels; i++)
    701                         buf[i] = sd[i];
    702                 }
    703                 else if( depth <= 16 )
    704                 {
    705                     const unsigned short *sd = img.ptr<unsigned short>(line);
    706                     for(int i = 0; i < width * channels; i++)
    707                         buf[i] = sd[i];
    708                 }
    709             }
    710             try
    711             {
    712                 file.writePixels( 1 );
    713             }
    714             catch(...)
    715             {
    716                 result = false;
    717                 break;
    718             }
    719         }
    720         delete[] buffer;
    721     }
    722 
    723     return result;
    724 }
    725 
    726 
    727 ImageEncoder ExrEncoder::newEncoder() const
    728 {
    729     return makePtr<ExrEncoder>();
    730 }
    731 
    732 }
    733 
    734 #endif
    735 
    736 /* End of file. */
    737