diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2017-10-19 04:55:11 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2017-11-08 01:20:22 +0300 |
commit | 05b08a3b6d864d760942c052a92c42c2bbe2c54d (patch) | |
tree | 75e2c34a06c0188672b25d2753e2d2f78ebb46f6 /source | |
parent | 2a097527f20da98bb4c1199c2854a15eea241153 (diff) |
Fix T53092: errors reading EXR files with different data/display window.
Multilayer/multiview OpenEXRs did not read the full data window like single
layer, now it should be consistent.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/imbuf/intern/openexr/openexr_api.cpp | 74 |
1 files changed, 45 insertions, 29 deletions
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index b3286bfbd98..451869415e7 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -1106,10 +1106,7 @@ void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, c void IMB_exr_read_channels(void *handle) { ExrHandle *data = (ExrHandle *)handle; - ExrChannel *echan; int numparts = data->ifile->parts(); - std::vector<FrameBuffer> frameBuffers(numparts); - std::vector<InputPart> inputParts; /* check if exr was saved with previous versions of blender which flipped images */ const StringAttribute *ta = data->ifile->header(0).findTypedAttribute <StringAttribute> ("BlenderMultiChannel"); @@ -1117,37 +1114,56 @@ void IMB_exr_read_channels(void *handle) exr_printf("\nIMB_exr_read_channels\n%s %-6s %-22s \"%s\"\n---------------------------------------------------------------------\n", "p", "view", "name", "internal_name"); - for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { - exr_printf("%d %-6s %-22s \"%s\"\n", echan->m->part_number, echan->m->view.c_str(), echan->m->name.c_str(), echan->m->internal_name.c_str()); + for (int i = 0; i < numparts; i++) { + /* Read part header. */ + InputPart in(*data->ifile, i); + Header header = in.header(); + Box2i dw = header.dataWindow(); + + /* Insert all matching channel into framebuffer. */ + FrameBuffer frameBuffer; + ExrChannel *echan; + + for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { + if(echan->m->part_number != i) { + continue; + } + + exr_printf("%d %-6s %-22s \"%s\"\n", echan->m->part_number, echan->m->view.c_str(), echan->m->name.c_str(), echan->m->internal_name.c_str()); + + if (echan->rect) { + float *rect = echan->rect; + size_t xstride = echan->xstride * sizeof(float); + size_t ystride = echan->ystride * sizeof(float); + + if (!flip) { + /* inverse correct first pixel for datawindow coordinates */ + rect -= echan->xstride * (dw.min.x - dw.min.y * data->width); + /* move to last scanline to flip to Blender convention */ + rect += echan->xstride * (data->height - 1) * data->width; + ystride = -ystride; + } + else { + /* inverse correct first pixel for datawindow coordinates */ + rect -= echan->xstride * (dw.min.x + dw.min.y * data->width); + } - if (echan->rect) { - if (flip) - frameBuffers[echan->m->part_number].insert(echan->m->internal_name, Slice(Imf::FLOAT, (char *)echan->rect, - echan->xstride * sizeof(float), echan->ystride * sizeof(float))); + frameBuffer.insert(echan->m->internal_name, Slice(Imf::FLOAT, (char *)rect, xstride, ystride)); + } else - frameBuffers[echan->m->part_number].insert(echan->m->internal_name, Slice(Imf::FLOAT, (char *)(echan->rect + echan->xstride * (data->height - 1) * data->width), - echan->xstride * sizeof(float), -echan->ystride * sizeof(float))); + printf("warning, channel with no rect set %s\n", echan->m->internal_name.c_str()); } - else - printf("warning, channel with no rect set %s\n", echan->m->internal_name.c_str()); - } - for (int i = 0; i < numparts; i++) { - InputPart in (*data->ifile, i); - in.setFrameBuffer(frameBuffers[i]); - inputParts.push_back(in); - } - - try { - for (int i = 0; i < numparts; i++) { - Header header = inputParts[i].header(); - exr_printf("readPixels:readPixels[%d]: min.y: %d, max.y: %d\n", i, header.dataWindow().min.y, header.dataWindow().max.y); - inputParts[i].readPixels(header.dataWindow().min.y, header.dataWindow().max.y); - inputParts[i].readPixels(0, data->height - 1); + /* Read pixels. */ + try { + in.setFrameBuffer(frameBuffer); + exr_printf("readPixels:readPixels[%d]: min.y: %d, max.y: %d\n", i, dw.min.y, dw.max.y); + in.readPixels(dw.min.y, dw.max.y); + } + catch (const std::exception& exc) { + std::cerr << "OpenEXR-readPixels: ERROR: " << exc.what() << std::endl; + break; } - } - catch (const std::exception& exc) { - std::cerr << "OpenEXR-readPixels: ERROR: " << exc.what() << std::endl; } } |