1
/************************************************************************/
3
/* Copyright 2007 by Pablo d'Angelo */
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 */
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 */
21
/* The above copyright notice and this permission notice shall be */
22
/* included in all copies or substantial portions of the */
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. */
34
/************************************************************************/
42
#include "vigra/config.hxx"
43
#include "vigra/sized_int.hxx"
44
#include "void_vector.hxx"
45
#include "auto_file.hxx"
47
#include "byteorder.hxx"
52
#include <ImfRgbaFile.h>
53
#include <ImfStringAttribute.h>
54
#include <ImfMatrixAttribute.h>
58
using namespace Imath;
62
CodecDesc ExrCodecFactory::getCodecDesc() const
67
desc.fileType = "EXR";
70
desc.pixelTypes.resize(1);
71
desc.pixelTypes[0] = "FLOAT";
73
// init compression types
74
desc.compressionTypes.resize(1);
75
desc.compressionTypes[0] = "LOSSLESS";
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';
85
// init file extensions
86
desc.fileExtensions.resize(1);
87
desc.fileExtensions[0] = "exr";
89
desc.bandNumbers.resize(1);
90
desc.bandNumbers[0] = 4;
95
std::auto_ptr<Decoder> ExrCodecFactory::getDecoder() const
97
return std::auto_ptr<Decoder>( new ExrDecoder() );
100
std::auto_ptr<Encoder> ExrCodecFactory::getEncoder() const
102
return std::auto_ptr<Encoder>( new ExrEncoder() );
105
struct ExrDecoderImpl
107
std::string filename;
111
// this is where libopenexr stores its state
115
ArrayVector<Rgba> pixels;
116
ArrayVector<float> bands;
125
int extra_components;
128
float x_resolution, y_resolution;
131
ExrDecoderImpl( const std::string & filename );
139
ExrDecoderImpl::ExrDecoderImpl( const std::string & filename )
140
#ifdef VIGRA_NEED_BIN_STREAMS
141
: file( filename.c_str() ),
143
: file( filename.c_str() ),
146
scanline(-1), width(0), height(0),
147
components(4), extra_components(1),
148
x_resolution(0), y_resolution(0)
152
ExrDecoderImpl::~ExrDecoderImpl()
156
void ExrDecoderImpl::init()
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;
164
position.x = dw.min.x;
166
position.y = dw.min.y;
168
// allocate data buffers
169
pixels.resize(width);
170
bands.resize(4*width);
173
void ExrDecoderImpl::nextScanline()
175
file.setFrameBuffer (pixels.data() - position.x - scanline * width, 1, width);
176
file.readPixels (scanline, 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;
188
void ExrDecoder::init( const std::string & filename )
190
pimpl = new ExrDecoderImpl(filename);
194
ExrDecoder::~ExrDecoder()
199
std::string ExrDecoder::getFileType() const
204
unsigned int ExrDecoder::getWidth() const
209
unsigned int ExrDecoder::getHeight() const
211
return pimpl->height;
214
unsigned int ExrDecoder::getNumBands() const
216
return pimpl->components;
219
unsigned int ExrDecoder::getNumExtraBands() const
221
return pimpl->extra_components;
224
float ExrDecoder::getXResolution() const
226
return pimpl->x_resolution;
229
float ExrDecoder::getYResolution() const
231
return pimpl->y_resolution;
234
Diff2D ExrDecoder::getPosition() const
236
return pimpl->position;
239
std::string ExrDecoder::getPixelType() const
244
unsigned int ExrDecoder::getOffset() const
246
return pimpl->components;
249
const void * ExrDecoder::currentScanlineOfBand( unsigned int band ) const
251
return pimpl->bands.begin() + band;
254
void ExrDecoder::nextScanline()
256
pimpl->nextScanline();
259
void ExrDecoder::close() {}
261
void ExrDecoder::abort() {}
263
struct ExrEncoderImpl
265
std::string filename;
267
RgbaOutputFile *file;
270
ArrayVector<float> bands;
271
ArrayVector<Rgba> pixels;
273
// image header fields
274
int width, height, components;
275
int extra_components;
276
int bit_depth, color_type;
284
// image layer position
288
float x_resolution, y_resolution;
291
ExrEncoderImpl( const std::string & filename );
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)
307
ExrEncoderImpl::~ExrEncoderImpl()
313
void ExrEncoderImpl::finalize()
316
bands.resize( 4 * width );
317
pixels.resize(width);
319
file = new RgbaOutputFile( filename.c_str(), width, height, WRITE_RGBA );
320
// enter finalized state
324
void ExrEncoderImpl::nextScanline()
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++) {
331
pixels[i].r = *src++;
332
pixels[i].g = *src++;
333
pixels[i].b = *src++;
334
pixels[i].a = *src++;
336
file->setFrameBuffer (pixels.begin()-scanline*width, 1, width);
337
file->writePixels (1);
342
void ExrEncoderImpl::close()
348
void ExrEncoder::init( const std::string & filename )
350
pimpl = new ExrEncoderImpl(filename);
353
ExrEncoder::~ExrEncoder()
358
std::string ExrEncoder::getFileType() const
363
void ExrEncoder::setWidth( unsigned int width )
365
VIGRA_IMPEX_FINALIZED(pimpl->finalized);
366
pimpl->width = width;
369
void ExrEncoder::setHeight( unsigned int height )
371
VIGRA_IMPEX_FINALIZED(pimpl->finalized);
372
pimpl->height = height;
375
void ExrEncoder::setNumBands( unsigned int bands )
378
vigra_fail( "internal error: number of components not supported." );
379
pimpl->components = bands;
382
void ExrEncoder::setCompressionType( const std::string & comp,
385
// TODO: support compression types
388
void ExrEncoder::setPosition( const Diff2D & pos )
390
VIGRA_IMPEX_FINALIZED(pimpl->finalized);
391
pimpl->position = pos;
394
void ExrEncoder::setXResolution( float xres )
396
VIGRA_IMPEX_FINALIZED(pimpl->finalized);
397
pimpl->x_resolution = xres;
400
void ExrEncoder::setYResolution( float yres )
402
VIGRA_IMPEX_FINALIZED(pimpl->finalized);
403
pimpl->y_resolution = yres;
406
void ExrEncoder::setPixelType( const std::string & pixelType )
408
VIGRA_IMPEX_FINALIZED(pimpl->finalized);
409
if ( pixelType != "FLOAT" )
410
vigra_fail( "internal error: pixeltype not supported." );
413
unsigned int ExrEncoder::getOffset() const
415
return pimpl->components;
418
void ExrEncoder::finalizeSettings()
420
VIGRA_IMPEX_FINALIZED(pimpl->finalized);
424
void * ExrEncoder::currentScanlineOfBand( unsigned int band )
426
return pimpl->bands.begin() + band;
429
void ExrEncoder::nextScanline()
432
pimpl->nextScanline();
435
void ExrEncoder::close()
440
void ExrEncoder::abort() {}