diff options
Diffstat (limited to 'source/blender/imbuf/intern/openexr/openexr_api.cpp')
-rw-r--r-- | source/blender/imbuf/intern/openexr/openexr_api.cpp | 95 |
1 files changed, 51 insertions, 44 deletions
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index b124cb2f80c..b59908fef39 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -180,7 +180,7 @@ static void openexr_header_compression(Header *header, int compression) static short imb_save_openexr_half(struct ImBuf *ibuf, char *name, int flags) { - + int channels = ibuf->channels; int width = ibuf->x; int height = ibuf->y; int write_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; // summarize @@ -194,7 +194,7 @@ static short imb_save_openexr_half(struct ImBuf *ibuf, char *name, int flags) header.channels().insert ("R", Channel (HALF)); header.channels().insert ("G", Channel (HALF)); header.channels().insert ("B", Channel (HALF)); - if (ibuf->depth==32) + if (ibuf->depth==32 && channels >= 4) header.channels().insert ("A", Channel (HALF)); if (write_zbuf) // z we do as float always header.channels().insert ("Z", Channel (FLOAT)); @@ -207,29 +207,29 @@ static short imb_save_openexr_half(struct ImBuf *ibuf, char *name, int flags) RGBAZ *to = pixels; int xstride= sizeof (RGBAZ); int ystride= xstride*width; - + /* indicate used buffers */ frameBuffer.insert ("R", Slice (HALF, (char *) &pixels[0].r, xstride, ystride)); frameBuffer.insert ("G", Slice (HALF, (char *) &pixels[0].g, xstride, ystride)); frameBuffer.insert ("B", Slice (HALF, (char *) &pixels[0].b, xstride, ystride)); - if (ibuf->depth==32) + if (ibuf->depth==32 && channels >= 4) frameBuffer.insert ("A", Slice (HALF, (char *) &pixels[0].a, xstride, ystride)); if (write_zbuf) - frameBuffer.insert ("Z", Slice (FLOAT, (char *) ibuf->zbuf_float + 4*(height-1)*width, + frameBuffer.insert ("Z", Slice (FLOAT, (char *)(ibuf->zbuf_float + (height-1)*width), sizeof(float), sizeof(float) * -width)); if(ibuf->rect_float) { float *from; for (int i = ibuf->y-1; i >= 0; i--) { - from= ibuf->rect_float + 4*i*width; + from= ibuf->rect_float + channels*i*width; for (int j = ibuf->x; j > 0; j--) { to->r = from[0]; - to->g = from[1]; - to->b = from[2]; - to->a = from[3]; + to->g = (channels >= 2)? from[1]: from[0]; + to->b = (channels >= 3)? from[2]: from[0]; + to->a = (channels >= 4)? from[3]: from[0]; to++; from += 4; } } @@ -239,14 +239,14 @@ static short imb_save_openexr_half(struct ImBuf *ibuf, char *name, int flags) for (int i = ibuf->y-1; i >= 0; i--) { - from= (unsigned char *)(ibuf->rect + i*width); + from= (unsigned char *)ibuf->rect + channels*i*width; for (int j = ibuf->x; j > 0; j--) { to->r = (float)(from[0])/255.0; - to->g = (float)(from[1])/255.0; - to->b = (float)(from[2])/255.0; - to->a = (float)(from[3])/255.0; + to->g = (float)((channels >= 2)? from[1]: from[0])/255.0; + to->b = (float)((channels >= 3)? from[2]: from[0])/255.0; + to->a = (float)((channels >= 4)? from[3]: from[0])/255.0; to++; from += 4; } } @@ -272,7 +272,7 @@ static short imb_save_openexr_half(struct ImBuf *ibuf, char *name, int flags) static short imb_save_openexr_float(struct ImBuf *ibuf, char *name, int flags) { - + int channels = ibuf->channels; int width = ibuf->x; int height = ibuf->y; int write_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; // summarize @@ -286,24 +286,29 @@ static short imb_save_openexr_float(struct ImBuf *ibuf, char *name, int flags) header.channels().insert ("R", Channel (FLOAT)); header.channels().insert ("G", Channel (FLOAT)); header.channels().insert ("B", Channel (FLOAT)); - if (ibuf->depth==32) + if (ibuf->depth==32 && channels >= 4) header.channels().insert ("A", Channel (FLOAT)); if (write_zbuf) header.channels().insert ("Z", Channel (FLOAT)); FrameBuffer frameBuffer; OutputFile *file = new OutputFile(name, header); - float *first= ibuf->rect_float + 4*(height-1)*width; - int xstride = sizeof(float) * 4; + int xstride = sizeof(float) * channels; int ystride = - xstride*width; - - frameBuffer.insert ("R", Slice (FLOAT, (char *) first, xstride, ystride)); - frameBuffer.insert ("G", Slice (FLOAT, (char *) (first+1), xstride, ystride)); - frameBuffer.insert ("B", Slice (FLOAT, (char *) (first+2), xstride, ystride)); - if (ibuf->depth==32) - frameBuffer.insert ("A", Slice (FLOAT, (char *) (first+3), xstride, ystride)); + 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[2]= (channels >= 3)? rect[0]+2: rect[0]; + rect[3]= (channels >= 4)? rect[0]+3: rect[0]; + + frameBuffer.insert ("R", Slice (FLOAT, (char *)rect[0], xstride, ystride)); + frameBuffer.insert ("G", Slice (FLOAT, (char *)rect[1], xstride, ystride)); + frameBuffer.insert ("B", Slice (FLOAT, (char *)rect[2], xstride, ystride)); + if (ibuf->depth==32 && channels >= 4) + frameBuffer.insert ("A", Slice (FLOAT, (char *)rect[3], xstride, ystride)); if (write_zbuf) - frameBuffer.insert ("Z", Slice (FLOAT, (char *) ibuf->zbuf_float + 4*(height-1)*width, + frameBuffer.insert ("Z", Slice (FLOAT, (char *) (ibuf->zbuf_float + (height-1)*width), sizeof(float), sizeof(float) * -width)); file->setFrameBuffer (frameBuffer); file->writePixels (height); @@ -362,6 +367,7 @@ typedef struct ExrHandle { OutputFile *ofile; int tilex, tiley; int width, height; + int mipmap; ListBase channels; /* flattened out, ExrChannel */ ListBase layers; /* hierarchical, pointing in end to ExrChannel */ @@ -450,7 +456,7 @@ void IMB_exr_begin_write(void *handle, char *filename, int width, int height, in data->ofile = new OutputFile(filename, header); } -void IMB_exrtile_begin_write(void *handle, char *filename, int width, int height, int tilex, int tiley) +void IMB_exrtile_begin_write(void *handle, char *filename, int mipmap, int width, int height, int tilex, int tiley) { ExrHandle *data= (ExrHandle *)handle; Header header (width, height); @@ -460,11 +466,12 @@ void IMB_exrtile_begin_write(void *handle, char *filename, int width, int height data->tiley= tiley; data->width= width; data->height= height; + data->mipmap= mipmap; for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next) header.channels().insert (echan->name, Channel (FLOAT)); - header.setTileDescription (TileDescription (tilex, tiley, ONE_LEVEL)); + header.setTileDescription (TileDescription (tilex, tiley, (mipmap)? MIPMAP_LEVELS: ONE_LEVEL)); header.lineOrder() = RANDOM_Y; header.compression() = RLE_COMPRESSION; @@ -478,7 +485,7 @@ int IMB_exr_begin_read(void *handle, char *filename, int *width, int *height) { ExrHandle *data= (ExrHandle *)handle; - if(BLI_exists(filename)) { + if(BLI_exists(filename) && BLI_filepathsize(filename)>32) { /* 32 is arbitrary, but zero length files crashes exr */ data->ifile = new InputFile(filename); if(data->ifile) { Box2i dw = data->ifile->header().dataWindow(); @@ -533,7 +540,7 @@ void IMB_exrtile_clear_channels(void *handle) BLI_freelistN(&data->channels); } -void IMB_exrtile_write_channels(void *handle, int partx, int party) +void IMB_exrtile_write_channels(void *handle, int partx, int party, int level) { ExrHandle *data= (ExrHandle *)handle; FrameBuffer frameBuffer; @@ -550,7 +557,7 @@ void IMB_exrtile_write_channels(void *handle, int partx, int party) try { // printf("write tile %d %d\n", partx/data->tilex, party/data->tiley); - data->tofile->writeTile (partx/data->tilex, party/data->tiley); + data->tofile->writeTile (partx/data->tilex, party/data->tiley, level); } catch (const std::exception &exc) { std::cerr << "OpenEXR-writeTile: ERROR: " << exc.what() << std::endl; @@ -620,7 +627,6 @@ void IMB_exr_multilayer_convert(void *handle, void *base, void IMB_exr_close(void *handle) { ExrHandle *data= (ExrHandle *)handle; - ExrChannel *echan; ExrLayer *lay; ExrPass *pass; @@ -783,28 +789,28 @@ static ExrHandle *imb_exr_begin_read_mem(InputFile *file, int width, int height) /* we can have RGB(A), XYZ(W), UVA */ if(pass->totchan==3 || pass->totchan==4) { if(pass->chan[0]->chan_id=='B' || pass->chan[1]->chan_id=='B' || pass->chan[2]->chan_id=='B') { - lookup['R']= 0; - lookup['G']= 1; - lookup['B']= 2; - lookup['A']= 3; + lookup[(unsigned int)'R']= 0; + lookup[(unsigned int)'G']= 1; + lookup[(unsigned int)'B']= 2; + lookup[(unsigned int)'A']= 3; } else if(pass->chan[0]->chan_id=='Y' || pass->chan[1]->chan_id=='Y' || pass->chan[2]->chan_id=='Y') { - lookup['X']= 0; - lookup['Y']= 1; - lookup['Z']= 2; - lookup['W']= 3; + lookup[(unsigned int)'X']= 0; + lookup[(unsigned int)'Y']= 1; + lookup[(unsigned int)'Z']= 2; + lookup[(unsigned int)'W']= 3; } else { - lookup['U']= 0; - lookup['V']= 1; - lookup['A']= 2; + lookup[(unsigned int)'U']= 0; + lookup[(unsigned int)'V']= 1; + lookup[(unsigned int)'A']= 2; } for(a=0; a<pass->totchan; a++) { echan= pass->chan[a]; - echan->rect= pass->rect + lookup[echan->chan_id]; + echan->rect= pass->rect + lookup[(unsigned int)echan->chan_id]; echan->xstride= pass->totchan; echan->ystride= width*pass->totchan; - pass->chan_id[ lookup[echan->chan_id] ]= echan->chan_id; + pass->chan_id[ (unsigned int)lookup[(unsigned int)echan->chan_id] ]= echan->chan_id; } } else { /* unknown */ @@ -836,6 +842,7 @@ typedef struct RGBA } RGBA; +#if 0 static void exr_print_filecontents(InputFile *file) { const ChannelList &channels = file->header().channels(); @@ -846,6 +853,7 @@ static void exr_print_filecontents(InputFile *file) printf("OpenEXR-load: Found channel %s of type %d\n", i.name(), channel.type); } } +#endif static int exr_has_zbuffer(InputFile *file) { @@ -853,7 +861,6 @@ static int exr_has_zbuffer(InputFile *file) for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) { - const Channel &channel = i.channel(); if(strcmp("Z", i.name())==0) return 1; } |