~ubuntu-branches/ubuntu/trusty/enblend-enfuse/trusty

« back to all changes in this revision

Viewing changes to src/vigra_impex/exr.cxx

  • Committer: Package Import Robot
  • Author(s): Jackson Doak
  • Date: 2014-01-22 06:23:44 UTC
  • mfrom: (5.1.6 sid)
  • Revision ID: package-import@ubuntu.com-20140122062344-gdj5nf671oxprqq7
Tags: 4.1.2+dfsg-2ubuntu1
* Merge from Debian, remaining changes:
  - Build-depend on libglew-dev rather than libglew1.5-dev | libglew1.4-dev
    | libglew-dev.
  - Build using -O1 on arm

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/************************************************************************/
2
 
/*                                                                      */
3
 
/*               Copyright 2007 by Pablo d'Angelo                       */
4
 
/*                                                                      */
5
 
/*    This file is part of the VIGRA computer vision library.           */
6
 
/*    The VIGRA Website is                                              */
7
 
/*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
8
 
/*    Please direct questions, bug reports, and contributions to        */
9
 
/*        koethe@informatik.uni-hamburg.de          or                  */
10
 
/*        vigra@kogs1.informatik.uni-hamburg.de                         */
11
 
/*                                                                      */
12
 
/*    Permission is hereby granted, free of charge, to any person       */
13
 
/*    obtaining a copy of this software and associated documentation    */
14
 
/*    files (the "Software"), to deal in the Software without           */
15
 
/*    restriction, including without limitation the rights to use,      */
16
 
/*    copy, modify, merge, publish, distribute, sublicense, and/or      */
17
 
/*    sell copies of the Software, and to permit persons to whom the    */
18
 
/*    Software is furnished to do so, subject to the following          */
19
 
/*    conditions:                                                       */
20
 
/*                                                                      */
21
 
/*    The above copyright notice and this permission notice shall be    */
22
 
/*    included in all copies or substantial portions of the             */
23
 
/*    Software.                                                         */
24
 
/*                                                                      */
25
 
/*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
26
 
/*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
27
 
/*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
28
 
/*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
29
 
/*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
30
 
/*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
31
 
/*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
32
 
/*    OTHER DEALINGS IN THE SOFTWARE.                                   */
33
 
/*                                                                      */
34
 
/************************************************************************/
35
 
 
36
 
#ifdef HAVE_CONFIG_H
37
 
#include <config.h>
38
 
#endif
39
 
 
40
 
#ifdef HasEXR
41
 
 
42
 
#include "vigra/config.hxx"
43
 
#include "vigra/sized_int.hxx"
44
 
#include "void_vector.hxx"
45
 
#include "auto_file.hxx"
46
 
#include "exr.hxx"
47
 
#include "byteorder.hxx"
48
 
#include "error.hxx"
49
 
#include <stdexcept>
50
 
#include <iostream>
51
 
 
52
 
#include <ImfRgbaFile.h>
53
 
#include <ImfStringAttribute.h>
54
 
#include <ImfMatrixAttribute.h>
55
 
#include <ImfArray.h>
56
 
 
57
 
using namespace Imf;
58
 
using namespace Imath;
59
 
 
60
 
namespace vigra {
61
 
 
62
 
    CodecDesc ExrCodecFactory::getCodecDesc() const
63
 
    {
64
 
        CodecDesc desc;
65
 
 
66
 
        // init file type
67
 
        desc.fileType = "EXR";
68
 
 
69
 
        // init pixel types
70
 
        desc.pixelTypes.resize(1);
71
 
        desc.pixelTypes[0] = "FLOAT";
72
 
 
73
 
        // init compression types
74
 
        desc.compressionTypes.resize(1);
75
 
        desc.compressionTypes[0] = "LOSSLESS";
76
 
 
77
 
        // init magic strings
78
 
        desc.magicStrings.resize(1);
79
 
        desc.magicStrings[0].resize(4);
80
 
        desc.magicStrings[0][0] = '\x76';
81
 
        desc.magicStrings[0][1] = '\x2f';
82
 
        desc.magicStrings[0][2] = '\x31';
83
 
        desc.magicStrings[0][3] = '\x01';
84
 
 
85
 
        // init file extensions
86
 
        desc.fileExtensions.resize(1);
87
 
        desc.fileExtensions[0] = "exr";
88
 
 
89
 
        desc.bandNumbers.resize(1);
90
 
        desc.bandNumbers[0] = 4;
91
 
 
92
 
        return desc;
93
 
    }
94
 
 
95
 
    std::auto_ptr<Decoder> ExrCodecFactory::getDecoder() const
96
 
    {
97
 
        return std::auto_ptr<Decoder>( new ExrDecoder() );
98
 
    }
99
 
 
100
 
    std::auto_ptr<Encoder> ExrCodecFactory::getEncoder() const
101
 
    {
102
 
        return std::auto_ptr<Encoder>( new ExrEncoder() );
103
 
    }
104
 
 
105
 
    struct ExrDecoderImpl
106
 
    {
107
 
        std::string filename;
108
 
        // data source
109
 
        // auto_file file;
110
 
 
111
 
        // this is where libopenexr stores its state
112
 
        RgbaInputFile file;
113
 
 
114
 
        // data container
115
 
        ArrayVector<Rgba> pixels;
116
 
        ArrayVector<float> bands;
117
 
 
118
 
        // scanline counter
119
 
        int scanline;
120
 
 
121
 
        int width;
122
 
        int height;
123
 
 
124
 
        int components;
125
 
        int extra_components;
126
 
        Diff2D position;
127
 
 
128
 
        float x_resolution, y_resolution;
129
 
 
130
 
        // ctor, dtor
131
 
        ExrDecoderImpl( const std::string & filename );
132
 
        ~ExrDecoderImpl();
133
 
 
134
 
        // methods
135
 
        void init();
136
 
        void nextScanline();
137
 
    };
138
 
 
139
 
    ExrDecoderImpl::ExrDecoderImpl( const std::string & filename )
140
 
#ifdef VIGRA_NEED_BIN_STREAMS
141
 
        : file( filename.c_str() ),
142
 
#else
143
 
        : file( filename.c_str() ),
144
 
#endif
145
 
          bands(0), 
146
 
          scanline(-1), width(0), height(0),
147
 
          components(4), extra_components(1),
148
 
          x_resolution(0), y_resolution(0)
149
 
    {
150
 
    }
151
 
 
152
 
    ExrDecoderImpl::~ExrDecoderImpl()
153
 
    {
154
 
    }
155
 
 
156
 
    void ExrDecoderImpl::init()
157
 
    {
158
 
        // setup framebuffer
159
 
        Box2i dw = file.header().dataWindow();
160
 
        Box2i dispw = file.header().displayWindow();
161
 
        width  = dw.max.x - dw.min.x + 1;
162
 
        height = dw.max.y - dw.min.y + 1;
163
 
 
164
 
        position.x = dw.min.x;
165
 
        scanline = dw.min.y;
166
 
        position.y = dw.min.y;
167
 
 
168
 
        // allocate data buffers
169
 
        pixels.resize(width);
170
 
        bands.resize(4*width);
171
 
    }
172
 
 
173
 
    void ExrDecoderImpl::nextScanline()
174
 
    {
175
 
        file.setFrameBuffer (pixels.data() - position.x - scanline * width, 1, width);
176
 
        file.readPixels (scanline, scanline);
177
 
        scanline++;
178
 
        // convert scanline to float
179
 
        float * dest = bands.begin();
180
 
        for (int i=0; i < width; i++) {
181
 
            *dest++ = pixels[i].r;
182
 
            *dest++ = pixels[i].g;
183
 
            *dest++ = pixels[i].b;
184
 
            *dest++ = pixels[i].a;
185
 
        }
186
 
    }
187
 
 
188
 
    void ExrDecoder::init( const std::string & filename )
189
 
    {
190
 
        pimpl = new ExrDecoderImpl(filename);
191
 
        pimpl->init();
192
 
    }
193
 
 
194
 
    ExrDecoder::~ExrDecoder()
195
 
    {
196
 
        delete pimpl;
197
 
    }
198
 
 
199
 
    std::string ExrDecoder::getFileType() const
200
 
    {
201
 
        return "EXR";
202
 
    }
203
 
 
204
 
    unsigned int ExrDecoder::getWidth() const
205
 
    {
206
 
        return pimpl->width;
207
 
    }
208
 
 
209
 
    unsigned int ExrDecoder::getHeight() const
210
 
    {
211
 
        return pimpl->height;
212
 
    }
213
 
 
214
 
    unsigned int ExrDecoder::getNumBands() const
215
 
    {
216
 
        return pimpl->components;
217
 
    }
218
 
 
219
 
    unsigned int ExrDecoder::getNumExtraBands() const
220
 
    {
221
 
        return pimpl->extra_components;
222
 
    }
223
 
 
224
 
    float ExrDecoder::getXResolution() const
225
 
    {
226
 
        return pimpl->x_resolution;
227
 
    }
228
 
 
229
 
    float ExrDecoder::getYResolution() const
230
 
    {
231
 
        return pimpl->y_resolution;
232
 
    }
233
 
 
234
 
    Diff2D ExrDecoder::getPosition() const
235
 
    {
236
 
        return pimpl->position;
237
 
    }
238
 
 
239
 
    std::string ExrDecoder::getPixelType() const
240
 
    {
241
 
        return "FLOAT";
242
 
    }
243
 
 
244
 
    unsigned int ExrDecoder::getOffset() const
245
 
    {
246
 
        return pimpl->components;
247
 
    }
248
 
 
249
 
    const void * ExrDecoder::currentScanlineOfBand( unsigned int band ) const
250
 
    {
251
 
        return pimpl->bands.begin() + band;
252
 
    }
253
 
 
254
 
    void ExrDecoder::nextScanline()
255
 
    {
256
 
        pimpl->nextScanline();
257
 
    }
258
 
 
259
 
    void ExrDecoder::close() {}
260
 
 
261
 
    void ExrDecoder::abort() {}
262
 
 
263
 
    struct ExrEncoderImpl
264
 
    {
265
 
        std::string filename;
266
 
        // data sink
267
 
        RgbaOutputFile *file;
268
 
 
269
 
        // data container
270
 
        ArrayVector<float> bands;
271
 
        ArrayVector<Rgba> pixels;
272
 
 
273
 
        // image header fields
274
 
        int width, height, components;
275
 
        int extra_components;
276
 
        int bit_depth, color_type;
277
 
 
278
 
        // scanline counter
279
 
        int scanline;
280
 
 
281
 
        // state
282
 
        bool finalized;
283
 
 
284
 
        // image layer position
285
 
        Diff2D position;
286
 
 
287
 
        // resolution
288
 
        float x_resolution, y_resolution;
289
 
 
290
 
        // ctor, dtor
291
 
        ExrEncoderImpl( const std::string & filename );
292
 
        ~ExrEncoderImpl();
293
 
 
294
 
        // methods
295
 
        void nextScanline();
296
 
        void finalize();
297
 
        void close();
298
 
    };
299
 
 
300
 
    ExrEncoderImpl::ExrEncoderImpl( const std::string & filename )
301
 
        : filename(filename), file(0), bands(0),
302
 
          scanline(0), finalized(false),
303
 
          x_resolution(0), y_resolution(0)
304
 
    {
305
 
    }
306
 
 
307
 
    ExrEncoderImpl::~ExrEncoderImpl()
308
 
    {
309
 
        if (file)
310
 
            delete file;
311
 
    }
312
 
 
313
 
    void ExrEncoderImpl::finalize()
314
 
    {
315
 
        // prepare the bands
316
 
        bands.resize( 4 * width );
317
 
        pixels.resize(width);
318
 
 
319
 
        file = new RgbaOutputFile( filename.c_str(), width, height, WRITE_RGBA );
320
 
        // enter finalized state
321
 
        finalized = true;
322
 
    }
323
 
 
324
 
    void ExrEncoderImpl::nextScanline()
325
 
    {
326
 
        // check if there are scanlines left at all, eventually write one
327
 
        if ( scanline < height ) {
328
 
            float * src = bands.data();
329
 
            for (int i=0; i < width; i++) {
330
 
                // convert to half
331
 
                pixels[i].r = *src++;
332
 
                pixels[i].g = *src++;
333
 
                pixels[i].b = *src++;
334
 
                pixels[i].a = *src++;
335
 
            }
336
 
            file->setFrameBuffer (pixels.begin()-scanline*width, 1, width);
337
 
            file->writePixels (1);
338
 
        }
339
 
        scanline++;
340
 
    }
341
 
 
342
 
    void ExrEncoderImpl::close()
343
 
    {
344
 
        delete file;
345
 
        file = 0;
346
 
    }
347
 
 
348
 
    void ExrEncoder::init( const std::string & filename )
349
 
    {
350
 
        pimpl = new ExrEncoderImpl(filename);
351
 
    }
352
 
 
353
 
    ExrEncoder::~ExrEncoder()
354
 
    {
355
 
        delete pimpl;
356
 
    }
357
 
 
358
 
    std::string ExrEncoder::getFileType() const
359
 
    {
360
 
        return "EXR";
361
 
    }
362
 
 
363
 
    void ExrEncoder::setWidth( unsigned int width )
364
 
    {
365
 
        VIGRA_IMPEX_FINALIZED(pimpl->finalized);
366
 
        pimpl->width = width;
367
 
    }
368
 
 
369
 
    void ExrEncoder::setHeight( unsigned int height )
370
 
    {
371
 
        VIGRA_IMPEX_FINALIZED(pimpl->finalized);
372
 
        pimpl->height = height;
373
 
    }
374
 
 
375
 
    void ExrEncoder::setNumBands( unsigned int bands )
376
 
    {
377
 
        if ( bands != 4 )
378
 
            vigra_fail( "internal error: number of components not supported." );
379
 
        pimpl->components = bands;
380
 
    }
381
 
 
382
 
    void ExrEncoder::setCompressionType( const std::string & comp,
383
 
                                         int quality )
384
 
    {
385
 
        // TODO: support compression types
386
 
    }
387
 
 
388
 
    void ExrEncoder::setPosition( const Diff2D & pos )
389
 
    {
390
 
        VIGRA_IMPEX_FINALIZED(pimpl->finalized);
391
 
        pimpl->position = pos;
392
 
    }
393
 
 
394
 
    void ExrEncoder::setXResolution( float xres )
395
 
    {
396
 
        VIGRA_IMPEX_FINALIZED(pimpl->finalized);
397
 
        pimpl->x_resolution = xres;
398
 
    }
399
 
 
400
 
    void ExrEncoder::setYResolution( float yres )
401
 
    {
402
 
        VIGRA_IMPEX_FINALIZED(pimpl->finalized);
403
 
        pimpl->y_resolution = yres;
404
 
    }
405
 
 
406
 
    void ExrEncoder::setPixelType( const std::string & pixelType )
407
 
    {
408
 
        VIGRA_IMPEX_FINALIZED(pimpl->finalized);
409
 
        if ( pixelType != "FLOAT" )
410
 
            vigra_fail( "internal error: pixeltype not supported." );
411
 
    }
412
 
 
413
 
    unsigned int ExrEncoder::getOffset() const
414
 
    {
415
 
        return pimpl->components;
416
 
    }
417
 
 
418
 
    void ExrEncoder::finalizeSettings()
419
 
    {
420
 
        VIGRA_IMPEX_FINALIZED(pimpl->finalized);
421
 
        pimpl->finalize();
422
 
    }
423
 
 
424
 
    void * ExrEncoder::currentScanlineOfBand( unsigned int band )
425
 
    {
426
 
        return pimpl->bands.begin() + band;
427
 
    }
428
 
 
429
 
    void ExrEncoder::nextScanline()
430
 
    {
431
 
        // write scanline
432
 
        pimpl->nextScanline();
433
 
    }
434
 
 
435
 
    void ExrEncoder::close()
436
 
    {
437
 
        pimpl->close();
438
 
    }
439
 
 
440
 
    void ExrEncoder::abort() {}
441
 
}
442
 
 
443
 
#endif // HasPNG