diff options
-rw-r--r-- | source/blender/imbuf/intern/openexr/openexr_api.cpp | 63 |
1 files changed, 57 insertions, 6 deletions
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 8d8bb938e98..2dca3114765 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -1124,6 +1124,27 @@ static const char *exr_rgba_channelname(InputFile *file, const char *chan) return chan; } +static bool exr_has_rgb(InputFile *file) +{ + return file->header().channels().findChannel("R") != NULL && + file->header().channels().findChannel("G") != NULL && + file->header().channels().findChannel("B") != NULL; +} + +static bool exr_has_luma(InputFile *file) +{ + /* Y channel is the luma and should always present fir luma space images, + * optionally it could be also channels for chromas called BY and RY. + */ + return file->header().channels().findChannel("Y") != NULL; +} + +static bool exr_has_chroma(InputFile *file) +{ + return file->header().channels().findChannel("BY") != NULL && + file->header().channels().findChannel("RY") != NULL; +} + static int exr_has_zbuffer(InputFile *file) { return !(file->header().channels().findChannel("Z") == NULL); @@ -1219,6 +1240,8 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char } } else { + const bool has_rgb = exr_has_rgb(file); + const bool has_luma = exr_has_luma(file); FrameBuffer frameBuffer; float *first; int xstride = sizeof(float) * 4; @@ -1231,12 +1254,22 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char /* but, since we read y-flipped (negative y stride) we move to last scanline */ first += 4 * (height - 1) * width; - frameBuffer.insert(exr_rgba_channelname(file, "R"), - Slice(Imf::FLOAT, (char *) first, xstride, ystride)); - frameBuffer.insert(exr_rgba_channelname(file, "G"), - Slice(Imf::FLOAT, (char *) (first + 1), xstride, ystride)); - frameBuffer.insert(exr_rgba_channelname(file, "B"), - Slice(Imf::FLOAT, (char *) (first + 2), xstride, ystride)); + if (has_rgb) { + frameBuffer.insert(exr_rgba_channelname(file, "R"), + Slice(Imf::FLOAT, (char *) first, xstride, ystride)); + frameBuffer.insert(exr_rgba_channelname(file, "G"), + Slice(Imf::FLOAT, (char *) (first + 1), xstride, ystride)); + frameBuffer.insert(exr_rgba_channelname(file, "B"), + Slice(Imf::FLOAT, (char *) (first + 2), xstride, ystride)); + } + else if (has_luma) { + frameBuffer.insert(exr_rgba_channelname(file, "Y"), + Slice(Imf::FLOAT, (char *) first, xstride, ystride)); + frameBuffer.insert(exr_rgba_channelname(file, "BY"), + Slice(Imf::FLOAT, (char *) (first + 1), xstride, ystride, 1, 1, 0.5f)); + frameBuffer.insert(exr_rgba_channelname(file, "RY"), + Slice(Imf::FLOAT, (char *) (first + 2), xstride, ystride, 1, 1, 0.5f)); + } /* 1.0 is fill value, this still needs to be assigned even when (is_alpha == 0) */ frameBuffer.insert(exr_rgba_channelname(file, "A"), @@ -1264,6 +1297,24 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char // if (flag & IM_rect) // IMB_rect_from_float(ibuf); + if (!has_rgb && has_luma) { + size_t a; + if (exr_has_chroma(file)) { + for (a = 0; a < (size_t) ibuf->x * ibuf->y; ++a) { + float *color = ibuf->rect_float + a * 4; + ycc_to_rgb(color[0] * 255.0f, color[1] * 255.0f, color[2] * 255.0f, + &color[0], &color[1], &color[2], + BLI_YCC_ITU_BT709); + } + } + else { + for (a = 0; a < (size_t) ibuf->x * ibuf->y; ++a) { + float *color = ibuf->rect_float + a * 4; + color[1] = color[2] = color[0]; + } + } + } + /* file is no longer needed */ delete file; } |