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