Skip to content

Commit f369bcb

Browse files
committed
Support for EXR grayscale images
1 parent f7919cb commit f369bcb

File tree

1 file changed

+65
-26
lines changed

1 file changed

+65
-26
lines changed

src/cinder/ImageFileTinyExr.cpp

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ ImageSourceFileTinyExr::ImageSourceFileTinyExr( DataSourceRef dataSource, ImageS
109109
setSize( mExrImage->width, mExrImage->height );
110110

111111
switch( mExrImage->num_channels ) {
112+
case 1:
113+
setColorModel( ImageIo::CM_GRAY );
114+
setChannelOrder( ImageIo::ChannelOrder::Y );
115+
break;
116+
case 2:
117+
setColorModel( ImageIo::CM_GRAY );
118+
setChannelOrder( ImageIo::ChannelOrder::YA );
119+
break;
112120
case 3:
113121
setColorModel( ImageIo::CM_RGB );
114122
setChannelOrder( ImageIo::ChannelOrder::RGB );
@@ -128,6 +136,7 @@ void ImageSourceFileTinyExr::load( ImageTargetRef target )
128136

129137
const size_t numChannels = mExrHeader->num_channels;
130138
const void * red = nullptr, *green = nullptr, *blue = nullptr, *alpha = nullptr;
139+
const void * gray = nullptr;
131140

132141
for( size_t c = 0; c < numChannels; ++c ) {
133142
if( strcmp( mExrHeader->channels[c].name, "R" ) == 0 )
@@ -138,38 +147,68 @@ void ImageSourceFileTinyExr::load( ImageTargetRef target )
138147
blue = mExrImage->images[c];
139148
else if( strcmp( mExrHeader->channels[c].name, "A" ) == 0 )
140149
alpha = mExrImage->images[c];
150+
else if( strcmp( mExrHeader->channels[c].name, "Y" ) == 0 )
151+
gray = mExrImage->images[c];
141152
}
142153

143-
if( ( !red ) || ( !green ) || ( !blue ) )
144-
throw ImageIoExceptionFailedLoadTinyExr( "Unable to locate channels for RGB" );
145-
146-
// load one interleaved row at a time
147-
if( getDataType() == ImageIo::FLOAT32 ) {
148-
vector<float> rowData( mWidth * mExrImage->num_channels, 0 );
149-
for( int32_t row = 0; row < mHeight; row++ ) {
150-
for( int32_t col = 0; col < mWidth; col++ ) {
151-
rowData.at( col * numChannels + 0 ) = static_cast<const float *>( red )[row * mWidth + col];
152-
rowData.at( col * numChannels + 1 ) = static_cast<const float *>( green )[row * mWidth + col];
153-
rowData.at( col * numChannels + 2 ) = static_cast<const float *>( blue )[row * mWidth + col];
154-
if( alpha )
155-
rowData.at( col * numChannels + 3 ) = static_cast<const float *>( alpha )[row * mWidth + col];
156-
}
154+
if( ( !gray ) && ( ( !red ) || ( !green ) || ( !blue ) ) )
155+
throw ImageIoExceptionFailedLoadTinyExr( "Unable to locate channels for Y or RGB" );
157156

158-
( ( *this ).*rowFunc )( target, row, rowData.data() );
157+
if( gray ) {
158+
if( getDataType() == ImageIo::FLOAT32 ) {
159+
vector<float> rowData( mWidth * mExrImage->num_channels, 0 );
160+
for( int32_t row = 0; row < mHeight; row++ ) {
161+
for( int32_t col = 0; col < mWidth; col++ ) {
162+
rowData.at( col * numChannels + 0 ) = static_cast<const float *>( gray )[row * mWidth + col];
163+
if( alpha )
164+
rowData.at( col * numChannels + 1 ) = static_cast<const float *>( alpha )[row * mWidth + col];
165+
}
166+
167+
( ( *this ).*rowFunc )( target, row, rowData.data() );
168+
}
169+
}
170+
else { // float16
171+
vector<uint16_t> rowData( mWidth * mExrImage->num_channels, 0 );
172+
for( int32_t row = 0; row < mHeight; row++ ) {
173+
for( int32_t col = 0; col < mWidth; col++ ) {
174+
rowData.at( col * numChannels + 0 ) = static_cast<const uint16_t *>( gray )[row * mWidth + col];
175+
if( alpha )
176+
rowData.at( col * numChannels + 1 ) = static_cast<const float *>( alpha )[row * mWidth + col];
177+
}
178+
179+
( ( *this ).*rowFunc )( target, row, rowData.data() );
180+
}
159181
}
160182
}
161-
else { // float16
162-
vector<uint16_t> rowData( mWidth * mExrImage->num_channels, 0 );
163-
for( int32_t row = 0; row < mHeight; row++ ) {
164-
for( int32_t col = 0; col < mWidth; col++ ) {
165-
rowData.at( col * numChannels + 0 ) = static_cast<const uint16_t *>( red )[row * mWidth + col];
166-
rowData.at( col * numChannels + 1 ) = static_cast<const uint16_t *>( green )[row * mWidth + col];
167-
rowData.at( col * numChannels + 2 ) = static_cast<const uint16_t *>( blue )[row * mWidth + col];
168-
if( alpha )
169-
rowData.at( col * numChannels + 3 ) = static_cast<const uint16_t *>( alpha )[row * mWidth + col];
183+
else {
184+
// load one interleaved row at a time
185+
if( getDataType() == ImageIo::FLOAT32 ) {
186+
vector<float> rowData( mWidth * mExrImage->num_channels, 0 );
187+
for( int32_t row = 0; row < mHeight; row++ ) {
188+
for( int32_t col = 0; col < mWidth; col++ ) {
189+
rowData.at( col * numChannels + 0 ) = static_cast<const float *>( red )[row * mWidth + col];
190+
rowData.at( col * numChannels + 1 ) = static_cast<const float *>( green )[row * mWidth + col];
191+
rowData.at( col * numChannels + 2 ) = static_cast<const float *>( blue )[row * mWidth + col];
192+
if( alpha )
193+
rowData.at( col * numChannels + 3 ) = static_cast<const float *>( alpha )[row * mWidth + col];
194+
}
195+
196+
( ( *this ).*rowFunc )( target, row, rowData.data() );
197+
}
198+
}
199+
else { // float16
200+
vector<uint16_t> rowData( mWidth * mExrImage->num_channels, 0 );
201+
for( int32_t row = 0; row < mHeight; row++ ) {
202+
for( int32_t col = 0; col < mWidth; col++ ) {
203+
rowData.at( col * numChannels + 0 ) = static_cast<const uint16_t *>( red )[row * mWidth + col];
204+
rowData.at( col * numChannels + 1 ) = static_cast<const uint16_t *>( green )[row * mWidth + col];
205+
rowData.at( col * numChannels + 2 ) = static_cast<const uint16_t *>( blue )[row * mWidth + col];
206+
if( alpha )
207+
rowData.at( col * numChannels + 3 ) = static_cast<const uint16_t *>( alpha )[row * mWidth + col];
208+
}
209+
210+
( ( *this ).*rowFunc )( target, row, rowData.data() );
170211
}
171-
172-
( ( *this ).*rowFunc )( target, row, rowData.data() );
173212
}
174213
}
175214
}

0 commit comments

Comments
 (0)