Changeset View
Changeset View
Standalone View
Standalone View
source/blender/imbuf/intern/openexr/openexr_api.cpp
| Show First 20 Lines • Show All 368 Lines • ▼ Show 20 Lines | |||||
| static void openexr_header_metadata_callback(void *data, const char *propname, char *prop, int UNUSED(len)) | static void openexr_header_metadata_callback(void *data, const char *propname, char *prop, int UNUSED(len)) | ||||
| { | { | ||||
| Header *header = (Header *)data; | Header *header = (Header *)data; | ||||
| header->insert(propname, StringAttribute(prop)); | header->insert(propname, StringAttribute(prop)); | ||||
| } | } | ||||
| static bool imb_save_openexr_half( | static bool imb_save_openexr_half( | ||||
| ImBuf *ibuf, const char *name, const int flags, const int totviews, | ImBuf *ibuf, const char *name, const int flags) | ||||
| const char * (*getview)(void *base, int view_id), | |||||
| ImBuf *(*getbuffer)(void *base, const int view_id)) | |||||
| { | { | ||||
| const int channels = ibuf->channels; | const int channels = ibuf->channels; | ||||
| const bool is_alpha = (channels >= 4) && (ibuf->planes == 32); | const bool is_alpha = (channels >= 4) && (ibuf->planes == 32); | ||||
| const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ | const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ | ||||
| const int width = ibuf->x; | const int width = ibuf->x; | ||||
| const int height = ibuf->y; | const int height = ibuf->y; | ||||
| const bool is_multiview = (flags & IB_multiview) && ibuf->userdata; | |||||
| BLI_assert((!is_multiview) || (getview && getbuffer)); | |||||
| std::vector <string> views; | |||||
| int view_id; | |||||
| try | try | ||||
| { | { | ||||
| Header header(width, height); | Header header(width, height); | ||||
| openexr_header_compression(&header, ibuf->foptions.flag & OPENEXR_COMPRESS); | openexr_header_compression(&header, ibuf->foptions.flag & OPENEXR_COMPRESS); | ||||
| openexr_header_metadata(&header, ibuf); | openexr_header_metadata(&header, ibuf); | ||||
| /* create views when possible */ | /* create channels */ | ||||
| for (view_id = 0; view_id < totviews; view_id ++) | header.channels().insert("R", Channel(HALF)); | ||||
| views.push_back(is_multiview ? getview(ibuf->userdata, view_id) : ""); | header.channels().insert("G", Channel(HALF)); | ||||
| header.channels().insert("B", Channel(HALF)); | |||||
| if (is_multiview) | |||||
| addMultiView(header, views); | |||||
| for (view_id = 0; view_id < totviews; view_id ++) { | |||||
| header.channels().insert(insertViewName("R", views, view_id), Channel(HALF)); | |||||
| header.channels().insert(insertViewName("G", views, view_id), Channel(HALF)); | |||||
| header.channels().insert(insertViewName("B", views, view_id), Channel(HALF)); | |||||
| if (is_alpha) | if (is_alpha) | ||||
| header.channels().insert(insertViewName("A", views, view_id), Channel(HALF)); | header.channels().insert("A", Channel(HALF)); | ||||
| if (is_zbuf) // z we do as float always | if (is_zbuf) // z we do as float always | ||||
| header.channels().insert(insertViewName("Z", views, view_id), Channel(Imf::FLOAT)); | header.channels().insert("Z", Channel(Imf::FLOAT)); | ||||
| } | |||||
| FrameBuffer frameBuffer; | FrameBuffer frameBuffer; | ||||
| /* manually create ofstream, so we can handle utf-8 filepaths on windows */ | /* manually create ofstream, so we can handle utf-8 filepaths on windows */ | ||||
| OFileStream file_stream(name); | OFileStream file_stream(name); | ||||
| OutputFile file(file_stream, header); | OutputFile file(file_stream, header); | ||||
| /* we store first everything in half array */ | /* we store first everything in half array */ | ||||
| std::vector<RGBAZ> pixels(height * width * totviews); | std::vector<RGBAZ> pixels(height * width); | ||||
| RGBAZ *to = &pixels[0]; | |||||
| int xstride = sizeof(RGBAZ); | int xstride = sizeof(RGBAZ); | ||||
| int ystride = xstride * width; | int ystride = xstride * width; | ||||
| for (view_id = 0; view_id < totviews; view_id ++) { | |||||
| ImBuf *view_ibuf = is_multiview ? getbuffer(ibuf->userdata, view_id) : ibuf; | |||||
| const size_t offset = view_id * width * height; | |||||
| RGBAZ *to = &pixels[offset]; | |||||
| /* TODO (dfelinto) | |||||
| * In some cases we get NULL ibufs, it needs investigation, meanwhile prevent crash | |||||
| * Multiview Render + Image Editor + OpenEXR + Multi-View | |||||
| */ | |||||
| if (view_ibuf == NULL) { | |||||
| throw std::runtime_error(std::string("Missing data to write to ") + name); | |||||
| } | |||||
| /* indicate used buffers */ | /* indicate used buffers */ | ||||
| frameBuffer.insert(insertViewName("R", views, view_id), Slice(HALF, (char *) &pixels[offset].r, xstride, ystride)); | frameBuffer.insert("R", Slice(HALF, (char *) &to->r, xstride, ystride)); | ||||
| frameBuffer.insert(insertViewName("G", views, view_id), Slice(HALF, (char *) &pixels[offset].g, xstride, ystride)); | frameBuffer.insert("G", Slice(HALF, (char *) &to->g, xstride, ystride)); | ||||
| frameBuffer.insert(insertViewName("B", views, view_id), Slice(HALF, (char *) &pixels[offset].b, xstride, ystride)); | frameBuffer.insert("B", Slice(HALF, (char *) &to->b, xstride, ystride)); | ||||
| if (is_alpha) | if (is_alpha) | ||||
| frameBuffer.insert(insertViewName("A", views, view_id), Slice(HALF, (char *) &pixels[offset].a, xstride, ystride)); | frameBuffer.insert("A", Slice(HALF, (char *) &to->a, xstride, ystride)); | ||||
| if (is_zbuf) | if (is_zbuf) | ||||
| frameBuffer.insert(insertViewName("Z", views, view_id), Slice(Imf::FLOAT, (char *)(view_ibuf->zbuf_float + (height - 1) * width), | frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *)(ibuf->zbuf_float + (height - 1) * width), | ||||
| sizeof(float), sizeof(float) * -width)); | sizeof(float), sizeof(float) * -width)); | ||||
| if (view_ibuf->rect_float) { | if (ibuf->rect_float) { | ||||
| float *from; | float *from; | ||||
| for (int i = view_ibuf->y - 1; i >= 0; i--) { | for (int i = ibuf->y - 1; i >= 0; i--) { | ||||
| from = view_ibuf->rect_float + channels * i * width; | from = ibuf->rect_float + channels * i * width; | ||||
| for (int j = view_ibuf->x; j > 0; j--) { | for (int j = ibuf->x; j > 0; j--) { | ||||
| to->r = from[0]; | to->r = from[0]; | ||||
| to->g = (channels >= 2) ? from[1] : from[0]; | to->g = (channels >= 2) ? from[1] : from[0]; | ||||
| to->b = (channels >= 3) ? from[2] : from[0]; | to->b = (channels >= 3) ? from[2] : from[0]; | ||||
| to->a = (channels >= 4) ? from[3] : 1.0f; | to->a = (channels >= 4) ? from[3] : 1.0f; | ||||
| to++; from += channels; | to++; from += channels; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| unsigned char *from; | unsigned char *from; | ||||
| for (int i = view_ibuf->y - 1; i >= 0; i--) { | for (int i = ibuf->y - 1; i >= 0; i--) { | ||||
| from = (unsigned char *)view_ibuf->rect + 4 * i * width; | from = (unsigned char *)ibuf->rect + 4 * i * width; | ||||
| for (int j = view_ibuf->x; j > 0; j--) { | for (int j = ibuf->x; j > 0; j--) { | ||||
| to->r = srgb_to_linearrgb((float)from[0] / 255.0f); | to->r = srgb_to_linearrgb((float)from[0] / 255.0f); | ||||
| to->g = srgb_to_linearrgb((float)from[1] / 255.0f); | to->g = srgb_to_linearrgb((float)from[1] / 255.0f); | ||||
| to->b = srgb_to_linearrgb((float)from[2] / 255.0f); | to->b = srgb_to_linearrgb((float)from[2] / 255.0f); | ||||
| to->a = channels >= 4 ? (float)from[3] / 255.0f : 1.0f; | to->a = channels >= 4 ? (float)from[3] / 255.0f : 1.0f; | ||||
| to++; from += 4; | to++; from += 4; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (is_multiview) | |||||
| IMB_freeImBuf(view_ibuf); | |||||
| } | |||||
| exr_printf("OpenEXR-save: Writing OpenEXR file of height %d.\n", height); | exr_printf("OpenEXR-save: Writing OpenEXR file of height %d.\n", height); | ||||
| file.setFrameBuffer(frameBuffer); | file.setFrameBuffer(frameBuffer); | ||||
| file.writePixels(height); | file.writePixels(height); | ||||
| } | } | ||||
| catch (const std::exception& exc) | catch (const std::exception& exc) | ||||
| { | { | ||||
| printf("OpenEXR-save: ERROR: %s\n", exc.what()); | printf("OpenEXR-save: ERROR: %s\n", exc.what()); | ||||
| return false; | return false; | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| static bool imb_save_openexr_float( | static bool imb_save_openexr_float( | ||||
| ImBuf *ibuf, const char *name, const int flags, const int totviews, | ImBuf *ibuf, const char *name, const int flags) | ||||
| const char * (*getview)(void *base, const int view_id), | |||||
| ImBuf *(*getbuffer)(void *base, const int view_id)) | |||||
| { | { | ||||
| const int channels = ibuf->channels; | const int channels = ibuf->channels; | ||||
| const bool is_alpha = (channels >= 4) && (ibuf->planes == 32); | const bool is_alpha = (channels >= 4) && (ibuf->planes == 32); | ||||
| const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ | const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ | ||||
| const int width = ibuf->x; | const int width = ibuf->x; | ||||
| const int height = ibuf->y; | const int height = ibuf->y; | ||||
| const bool is_multiview = (flags & IB_multiview) && ibuf->userdata; | |||||
| BLI_assert((!is_multiview) || (getview && getbuffer)); | |||||
| std::vector <string> views; | |||||
| int view_id; | |||||
| try | try | ||||
| { | { | ||||
| Header header(width, height); | Header header(width, height); | ||||
| openexr_header_compression(&header, ibuf->foptions.flag & OPENEXR_COMPRESS); | openexr_header_compression(&header, ibuf->foptions.flag & OPENEXR_COMPRESS); | ||||
| openexr_header_metadata(&header, ibuf); | openexr_header_metadata(&header, ibuf); | ||||
| /* create views when possible */ | /* create channels */ | ||||
| for (view_id = 0; view_id < totviews; view_id ++) | header.channels().insert("R", Channel(Imf::FLOAT)); | ||||
| views.push_back(is_multiview ? getview(ibuf->userdata, view_id) : ""); | header.channels().insert("G", Channel(Imf::FLOAT)); | ||||
| header.channels().insert("B", Channel(Imf::FLOAT)); | |||||
| if (is_multiview) | |||||
| addMultiView(header, views); | |||||
| for (view_id = 0; view_id < totviews; view_id ++) { | |||||
| header.channels().insert(insertViewName("R", views, view_id), Channel(Imf::FLOAT)); | |||||
| header.channels().insert(insertViewName("G", views, view_id), Channel(Imf::FLOAT)); | |||||
| header.channels().insert(insertViewName("B", views, view_id), Channel(Imf::FLOAT)); | |||||
| if (is_alpha) | if (is_alpha) | ||||
| header.channels().insert(insertViewName("A", views, view_id), Channel(Imf::FLOAT)); | header.channels().insert("A", Channel(Imf::FLOAT)); | ||||
| if (is_zbuf) | if (is_zbuf) | ||||
| header.channels().insert(insertViewName("Z", views, view_id), Channel(Imf::FLOAT)); | header.channels().insert("Z", Channel(Imf::FLOAT)); | ||||
| } | |||||
| FrameBuffer frameBuffer; | FrameBuffer frameBuffer; | ||||
| /* manually create ofstream, so we can handle utf-8 filepaths on windows */ | /* manually create ofstream, so we can handle utf-8 filepaths on windows */ | ||||
| OFileStream file_stream(name); | OFileStream file_stream(name); | ||||
| OutputFile file(file_stream, header); | OutputFile file(file_stream, header); | ||||
| int xstride = sizeof(float) * channels; | int xstride = sizeof(float) * channels; | ||||
| int ystride = -xstride * width; | int ystride = -xstride * width; | ||||
| for (view_id = 0; view_id < totviews; view_id ++) { | |||||
| float *rect[4] = {NULL, NULL, NULL, NULL}; | |||||
| ImBuf *view_ibuf = is_multiview ? getbuffer(ibuf->userdata, view_id) : ibuf; | |||||
| /* TODO (dfelinto) | |||||
| * In some cases we get NULL ibufs, it needs investigation, meanwhile prevent crash | |||||
| * Multiview Render + Image Editor + OpenEXR + Multi-View | |||||
| */ | |||||
| if (view_ibuf == NULL) { | |||||
| throw std::runtime_error(std::string("Missing data to write to ") + name); | |||||
| } | |||||
| /* last scanline, stride negative */ | /* last scanline, stride negative */ | ||||
| rect[0] = view_ibuf->rect_float + channels * (height - 1) * width; | float *rect[4] = {NULL, NULL, NULL, NULL}; | ||||
| rect[0] = ibuf->rect_float + channels * (height - 1) * width; | |||||
| rect[1] = (channels >= 2) ? rect[0] + 1 : rect[0]; | rect[1] = (channels >= 2) ? rect[0] + 1 : rect[0]; | ||||
| rect[2] = (channels >= 3) ? rect[0] + 2 : rect[0]; | rect[2] = (channels >= 3) ? rect[0] + 2 : rect[0]; | ||||
| rect[3] = (channels >= 4) ? rect[0] + 3 : rect[0]; /* red as alpha, is this needed since alpha isn't written? */ | rect[3] = (channels >= 4) ? rect[0] + 3 : rect[0]; /* red as alpha, is this needed since alpha isn't written? */ | ||||
| frameBuffer.insert(insertViewName("R", views, view_id), Slice(Imf::FLOAT, (char *)rect[0], xstride, ystride)); | frameBuffer.insert("R", Slice(Imf::FLOAT, (char *)rect[0], xstride, ystride)); | ||||
| frameBuffer.insert(insertViewName("G", views, view_id), Slice(Imf::FLOAT, (char *)rect[1], xstride, ystride)); | frameBuffer.insert("G", Slice(Imf::FLOAT, (char *)rect[1], xstride, ystride)); | ||||
| frameBuffer.insert(insertViewName("B", views, view_id), Slice(Imf::FLOAT, (char *)rect[2], xstride, ystride)); | frameBuffer.insert("B", Slice(Imf::FLOAT, (char *)rect[2], xstride, ystride)); | ||||
| if (is_alpha) | if (is_alpha) | ||||
| frameBuffer.insert(insertViewName("A", views, view_id), Slice(Imf::FLOAT, (char *)rect[3], xstride, ystride)); | frameBuffer.insert("A", Slice(Imf::FLOAT, (char *)rect[3], xstride, ystride)); | ||||
| if (is_zbuf) | if (is_zbuf) | ||||
| frameBuffer.insert(insertViewName("Z", views, view_id), Slice(Imf::FLOAT, (char *) (view_ibuf->zbuf_float + (height - 1) * width), | frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *) (ibuf->zbuf_float + (height - 1) * width), | ||||
| sizeof(float), sizeof(float) * -width)); | sizeof(float), sizeof(float) * -width)); | ||||
| if (is_multiview) | |||||
| IMB_freeImBuf(view_ibuf); | |||||
| } | |||||
| file.setFrameBuffer(frameBuffer); | file.setFrameBuffer(frameBuffer); | ||||
| file.writePixels(height); | file.writePixels(height); | ||||
| } | } | ||||
| catch (const std::exception& exc) | catch (const std::exception& exc) | ||||
| { | { | ||||
| printf("OpenEXR-save: ERROR: %s\n", exc.what()); | printf("OpenEXR-save: ERROR: %s\n", exc.what()); | ||||
| return false; | return false; | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| int imb_save_openexr(struct ImBuf *ibuf, const char *name, int flags) | int imb_save_openexr(struct ImBuf *ibuf, const char *name, int flags) | ||||
| { | { | ||||
| if (flags & IB_mem) { | if (flags & IB_mem) { | ||||
| printf("OpenEXR-save: Create EXR in memory CURRENTLY NOT SUPPORTED !\n"); | printf("OpenEXR-save: Create EXR in memory CURRENTLY NOT SUPPORTED !\n"); | ||||
| imb_addencodedbufferImBuf(ibuf); | imb_addencodedbufferImBuf(ibuf); | ||||
| ibuf->encodedsize = 0; | ibuf->encodedsize = 0; | ||||
| return(0); | return(0); | ||||
| } | } | ||||
| if (ibuf->foptions.flag & OPENEXR_HALF) | if (ibuf->foptions.flag & OPENEXR_HALF) | ||||
| return (int) imb_save_openexr_half(ibuf, name, flags, 1, NULL, NULL); | return (int) imb_save_openexr_half(ibuf, name, flags); | ||||
| else { | |||||
| /* when no float rect, we save as half (16 bits is sufficient) */ | |||||
| if (ibuf->rect_float == NULL) | |||||
| return (int) imb_save_openexr_half(ibuf, name, flags, 1, NULL, NULL); | |||||
| else | |||||
| return (int) imb_save_openexr_float(ibuf, name, flags, 1, NULL, NULL); | |||||
| } | |||||
| } | |||||
| static bool imb_save_openexr_multiview( | |||||
| ImBuf *ibuf, const char *name, const int flags, const int totviews, | |||||
| const char *(*getview)(void *base, const int view_id), | |||||
| ImBuf *(*getbuffer)(void *base, const int view_id)) | |||||
| { | |||||
| if (flags & IB_mem) { | |||||
| printf("OpenEXR-save: Create multiview EXR in memory CURRENTLY NOT SUPPORTED !\n"); | |||||
| imb_addencodedbufferImBuf(ibuf); | |||||
| ibuf->encodedsize = 0; | |||||
| return false; | |||||
| } | |||||
| if (ibuf->foptions.flag & OPENEXR_HALF) | |||||
| return imb_save_openexr_half(ibuf, name, flags, totviews, getview, getbuffer); | |||||
| else { | else { | ||||
| /* when no float rect, we save as half (16 bits is sufficient) */ | /* when no float rect, we save as half (16 bits is sufficient) */ | ||||
| if (ibuf->rect_float == NULL) | if (ibuf->rect_float == NULL) | ||||
| return imb_save_openexr_half(ibuf, name, flags, totviews, getview, getbuffer); | return (int) imb_save_openexr_half(ibuf, name, flags); | ||||
| else | else | ||||
| return imb_save_openexr_float(ibuf, name, flags, totviews, getview, getbuffer); | return (int) imb_save_openexr_float(ibuf, name, flags); | ||||
| } | |||||
| } | } | ||||
| /* Save single-layer multiview OpenEXR | |||||
| * If we have more multiview formats in the future, the function below could be incorporated | |||||
| * in our ImBuf write functions, meanwhile this is an OpenEXR special case only */ | |||||
| bool IMB_exr_multiview_save( | |||||
| ImBuf *ibuf, const char *name, const int flags, const int totviews, | |||||
| const char *(*getview)(void *base, const int view_id), | |||||
| ImBuf *(*getbuffer)(void *base, const int view_id)) | |||||
| { | |||||
| return imb_save_openexr_multiview(ibuf, name, flags, totviews, getview, getbuffer); | |||||
| } | } | ||||
| /* ********************* Nicer API, MultiLayer and with Tile file support ************************************ */ | /* ********************* Nicer API, MultiLayer and with Tile file support ************************************ */ | ||||
| /* naming rules: | /* naming rules: | ||||
| * - parse name from right to left | * - parse name from right to left | ||||
| * - last character is channel ID, 1 char like 'A' 'R' 'G' 'B' 'X' 'Y' 'Z' 'W' 'U' 'V' | * - last character is channel ID, 1 char like 'A' 'R' 'G' 'B' 'X' 'Y' 'Z' 'W' 'U' 'V' | ||||
| * - separated with a dot; the Pass name (like "Depth", "Color", "Diffuse" or "Combined") | * - separated with a dot; the Pass name (like "Depth", "Color", "Diffuse" or "Combined") | ||||
| ▲ Show 20 Lines • Show All 542 Lines • ▼ Show 20 Lines | try { | ||||
| // printf("write tile %d %d\n", partx/data->tilex, party/data->tiley); | // printf("write tile %d %d\n", partx/data->tilex, party/data->tiley); | ||||
| out.writeTile(partx / data->tilex, party / data->tiley, level); | out.writeTile(partx / data->tilex, party / data->tiley, level); | ||||
| } | } | ||||
| catch (const std::exception& exc) { | catch (const std::exception& exc) { | ||||
| std::cerr << "OpenEXR-writeTile: ERROR: " << exc.what() << std::endl; | std::cerr << "OpenEXR-writeTile: ERROR: " << exc.what() << std::endl; | ||||
| } | } | ||||
| } | } | ||||
| /* called only when handle has all views */ | |||||
| void IMB_exrmultiview_write_channels(void *handle, const char *viewname) | |||||
| { | |||||
| ExrHandle *data = (ExrHandle *)handle; | |||||
| const int view_id = viewname ? imb_exr_get_multiView_id(*data->multiView, viewname) : -1; | |||||
| int numparts = (view_id == -1 ? data->parts : view_id + 1); | |||||
| std::vector <FrameBuffer> frameBuffers(numparts); | |||||
| std::vector <OutputPart> outputParts; | |||||
| ExrChannel *echan; | |||||
| int i, part; | |||||
| if (data->channels.first == NULL) | |||||
| return; | |||||
| exr_printf("\nIMB_exrmultiview_write_channels()\n"); | |||||
| for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { | |||||
| if (view_id != -1 && echan->view_id != view_id) | |||||
| continue; | |||||
| part = (view_id == -1 ? echan->m->part_number : echan->view_id); | |||||
| /* last scanline, stride negative */ | |||||
| float *rect = echan->rect + echan->xstride * (data->height - 1) * data->width; | |||||
| frameBuffers[part].insert(echan->m->internal_name, | |||||
| Slice(Imf::FLOAT, | |||||
| (char *)rect, | |||||
| echan->xstride * sizeof(float), | |||||
| -echan->ystride * sizeof(float)) | |||||
| ); | |||||
| } | |||||
| for (i = 0; i < numparts; i++) { | |||||
| OutputPart out(*data->mpofile, i); | |||||
| out.setFrameBuffer(frameBuffers[i]); | |||||
| outputParts.push_back(out); | |||||
| } | |||||
| try { | |||||
| for (i = 0; i < numparts; i++) { | |||||
| if (view_id != -1 && i != view_id) | |||||
| continue; | |||||
| outputParts[i].writePixels(data->height); | |||||
| } | |||||
| } | |||||
| catch (const std::exception& exc) { | |||||
| std::cerr << "OpenEXR-write Multi Part: ERROR: " << exc.what() << std::endl; | |||||
| } | |||||
| } | |||||
| void IMB_exr_read_channels(void *handle) | void IMB_exr_read_channels(void *handle) | ||||
| { | { | ||||
| ExrHandle *data = (ExrHandle *)handle; | ExrHandle *data = (ExrHandle *)handle; | ||||
| ExrChannel *echan; | ExrChannel *echan; | ||||
| int numparts = data->ifile->parts(); | int numparts = data->ifile->parts(); | ||||
| std::vector<FrameBuffer> frameBuffers(numparts); | std::vector<FrameBuffer> frameBuffers(numparts); | ||||
| std::vector<InputPart> inputParts; | std::vector<InputPart> inputParts; | ||||
| ▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | if (laybase) { | ||||
| for (pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) { | for (pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) { | ||||
| addpass(base, laybase, pass->internal_name, pass->rect, pass->totchan, pass->chan_id, pass->view); | addpass(base, laybase, pass->internal_name, pass->rect, pass->totchan, pass->chan_id, pass->view); | ||||
| pass->rect = NULL; | pass->rect = NULL; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void IMB_exr_multiview_convert(void *handle, void *base, | |||||
| void (*addview)(void *base, const char *str), | |||||
| void (*addbuffer)(void *base, const char *str, ImBuf *ibuf, const int frame), | |||||
| const int frame) | |||||
| { | |||||
| ExrHandle *data = (ExrHandle *)handle; | |||||
| MultiPartInputFile *file = data->ifile; | |||||
| ExrLayer *lay; | |||||
| ExrPass *pass; | |||||
| ImBuf *ibuf = NULL; | |||||
| const bool is_alpha = exr_has_alpha(*file); | |||||
| Box2i dw = file->header(0).dataWindow(); | |||||
| const size_t width = dw.max.x - dw.min.x + 1; | |||||
| const size_t height = dw.max.y - dw.min.y + 1; | |||||
| const bool is_depth = exr_has_zbuffer(*file); | |||||
| /* add views to RenderResult */ | |||||
| for (StringVector::const_iterator i = data->multiView->begin(); i != data->multiView->end(); ++i) { | |||||
| addview(base, (*i).c_str()); | |||||
| } | |||||
| if (BLI_listbase_is_empty(&data->layers)) { | |||||
| printf("cannot convert multiviews, no views in handle\n"); | |||||
| return; | |||||
| } | |||||
| /* there is one float/pass per layer (layer here is a view) */ | |||||
| BLI_assert(BLI_listbase_count_ex(&data->layers, 2) == 1); | |||||
| lay = (ExrLayer *)data->layers.first; | |||||
| for (pass = (ExrPass *)lay->passes.first; pass; pass = pass->next) { | |||||
| if (STREQ(pass->chan_id, "RGB") || STREQ(pass->chan_id, "RGBA")) { | |||||
| ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, IB_rectfloat); | |||||
| if (!ibuf) { | |||||
| printf("error creating multiview buffer\n"); | |||||
| return; | |||||
| } | |||||
| IMB_buffer_float_from_float( | |||||
| ibuf->rect_float, pass->rect, pass->totchan, | |||||
| IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false, | |||||
| ibuf->x, ibuf->y, ibuf->x, ibuf->x); | |||||
| if (hasXDensity(file->header(0))) { | |||||
| ibuf->ppm[0] = xDensity(file->header(0)) * 39.3700787f; | |||||
| ibuf->ppm[1] = ibuf->ppm[0] * (double)file->header(0).pixelAspectRatio(); | |||||
| } | |||||
| if (is_depth) { | |||||
| ExrPass *zpass; | |||||
| for (zpass = (ExrPass *)lay->passes.first; zpass; zpass = zpass->next) { | |||||
| if (STREQ(zpass->chan_id, "Z") && STREQ(zpass->view, pass->view)) { | |||||
| addzbuffloatImBuf(ibuf); | |||||
| memcpy(ibuf->zbuf_float, zpass->rect, sizeof(float) * ibuf->x * ibuf->y); | |||||
| } | |||||
| } | |||||
| } | |||||
| addbuffer(base, pass->view, ibuf, frame); | |||||
| } | |||||
| } | |||||
| } | |||||
| void IMB_exr_close(void *handle) | void IMB_exr_close(void *handle) | ||||
| { | { | ||||
| ExrHandle *data = (ExrHandle *)handle; | ExrHandle *data = (ExrHandle *)handle; | ||||
| ExrLayer *lay; | ExrLayer *lay; | ||||
| ExrPass *pass; | ExrPass *pass; | ||||
| ExrChannel *chan; | ExrChannel *chan; | ||||
| delete data->ifile; | delete data->ifile; | ||||
| ▲ Show 20 Lines • Show All 454 Lines • ▼ Show 20 Lines | else { | ||||
| *r_singlelayer = true; | *r_singlelayer = true; | ||||
| *r_multilayer = false; | *r_multilayer = false; | ||||
| *r_multiview = false; | *r_multiview = false; | ||||
| } | } | ||||
| BLI_assert(r_singlelayer != r_multilayer); | BLI_assert(r_singlelayer != r_multilayer); | ||||
| } | } | ||||
| bool IMB_exr_has_singlelayer_multiview(void *handle) | |||||
| { | |||||
| ExrHandle *data = (ExrHandle *)handle; | |||||
| MultiPartInputFile *file = data->ifile; | |||||
| std::set <std::string> layerNames; | |||||
| const ChannelList& channels = file->header(0).channels(); | |||||
| const StringAttribute *comments; | |||||
| if (exr_has_multiview(*file) == false) | |||||
| return false; | |||||
| comments = file->header(0).findTypedAttribute<StringAttribute>("BlenderMultiChannel"); | |||||
| if (comments) | |||||
| return false; | |||||
| /* will not include empty layer names */ | |||||
| channels.layers(layerNames); | |||||
| /* returns false if any layer differs from views list */ | |||||
| if (layerNames.size()) | |||||
| for (std::set<string>::iterator i = layerNames.begin(); i != layerNames.end(); i++) | |||||
| if (imb_exr_get_multiView_id(*data->multiView, *i) == -1) | |||||
| return false; | |||||
| return true; | |||||
| } | |||||
| bool IMB_exr_has_multilayer(void *handle) | |||||
| { | |||||
| ExrHandle *data = (ExrHandle *)handle; | |||||
| return imb_exr_is_multilayer_file(*data->ifile); | |||||
| } | |||||
| static bool exr_has_multiview(MultiPartInputFile& file) | static bool exr_has_multiview(MultiPartInputFile& file) | ||||
| { | { | ||||
| return hasMultiView(file.header(0)); | return hasMultiView(file.header(0)); | ||||
| } | } | ||||
| static bool exr_has_multipart_file(MultiPartInputFile& file) | static bool exr_has_multipart_file(MultiPartInputFile& file) | ||||
| { | { | ||||
| return file.parts() > 1; | return file.parts() > 1; | ||||
| Show All 10 Lines | if (exr_has_multiview(file)) | ||||
| return true; | return true; | ||||
| if (imb_exr_is_multilayer_file(file)) | if (imb_exr_is_multilayer_file(file)) | ||||
| return true; | return true; | ||||
| return false; | return false; | ||||
| } | } | ||||
| bool IMB_exr_has_multilayer(void *handle) | |||||
| { | |||||
| ExrHandle *data = (ExrHandle *)handle; | |||||
| return imb_exr_is_multi(*data->ifile); | |||||
| } | |||||
| struct ImBuf *imb_load_openexr(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) | struct ImBuf *imb_load_openexr(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) | ||||
| { | { | ||||
| struct ImBuf *ibuf = NULL; | struct ImBuf *ibuf = NULL; | ||||
| Mem_IStream *membuf = NULL; | Mem_IStream *membuf = NULL; | ||||
| MultiPartInputFile *file = NULL; | MultiPartInputFile *file = NULL; | ||||
| if (imb_is_a_openexr(mem) == 0) return(NULL); | if (imb_is_a_openexr(mem) == 0) return(NULL); | ||||
| ▲ Show 20 Lines • Show All 174 Lines • Show Last 20 Lines | |||||