diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-08-24 16:10:35 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-08-24 16:10:35 +0400 |
commit | 61a39c7b1756cebb4a13949b5a880aa9d0d4ee3e (patch) | |
tree | fe44acb063021684089a4eb325423c3f9ee9d885 /source/blender/imbuf | |
parent | 7a66f139b4283dd4cf3ad0936d825cb905bfc676 (diff) |
Fix second part #32377: saving/loading exr files to file paths with non-ascii
characters should now work on Windows.
Diffstat (limited to 'source/blender/imbuf')
-rw-r--r-- | source/blender/imbuf/intern/openexr/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/imbuf/intern/openexr/SConscript | 4 | ||||
-rw-r--r-- | source/blender/imbuf/intern/openexr/openexr_api.cpp | 135 |
3 files changed, 122 insertions, 18 deletions
diff --git a/source/blender/imbuf/intern/openexr/CMakeLists.txt b/source/blender/imbuf/intern/openexr/CMakeLists.txt index 4ee2ff4cc47..a5afc1abdc6 100644 --- a/source/blender/imbuf/intern/openexr/CMakeLists.txt +++ b/source/blender/imbuf/intern/openexr/CMakeLists.txt @@ -31,6 +31,7 @@ set(INC ../../../blenlib ../../../makesdna ../../../../../intern/guardedalloc + ../../../../../intern/utfconv ) set(INC_SYS diff --git a/source/blender/imbuf/intern/openexr/SConscript b/source/blender/imbuf/intern/openexr/SConscript index e590077db2b..a6c5ad984e2 100644 --- a/source/blender/imbuf/intern/openexr/SConscript +++ b/source/blender/imbuf/intern/openexr/SConscript @@ -10,7 +10,9 @@ incs = ['.', '../../../blenlib', 'intern/include', '#/intern/guardedalloc', - '../../../makesdna'] + '../../../makesdna', + '#/intern/utfconv'] + incs += Split(env['BF_OPENEXR_INC']) defs = ['WITH_OPENEXR'] diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 91876249bf6..1b99a3040a8 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -32,12 +32,17 @@ #include <stdlib.h> #include <stdio.h> #include <stddef.h> +#include <fstream> #include <string> #include <set> #include <openexr_api.h> +#if defined (WIN32) && !defined(FREE_WINDOWS) +#include "utfconv.h" +#endif + extern "C" { @@ -76,6 +81,7 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) #include <IlmImf/ImfCompression.h> #include <IlmImf/ImfCompressionAttribute.h> #include <IlmImf/ImfStringAttribute.h> +#include <IlmImf/ImfStdIO.h> #include <Imath/ImathBox.h> #else #include <half.h> @@ -90,6 +96,7 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) #include <ImfCompression.h> #include <ImfCompressionAttribute.h> #include <ImfStringAttribute.h> +#include <ImfStdIO.h> #endif using namespace Imf; @@ -192,6 +199,28 @@ static void openexr_header_metadata(Header *header, struct ImBuf *ibuf) header->insert(info->key, StringAttribute(info->value)); } +static void openexr_ofstream_open(std::ofstream& ofs, const char *name) +{ +#if defined (WIN32) && !defined(FREE_WINDOWS) + wchar_t *wname = alloc_utf16_from_8(name, 0); + ofs.open(wname, std::ios_base::binary); + free(wname); +#else + ofs.open(name, std::ios_base::binary); +#endif +} + +static void openexr_ifstream_open(std::ifstream& ifs, const char *name) +{ +#if defined (WIN32) && !defined(FREE_WINDOWS) + wchar_t *wname = alloc_utf16_from_8(name, 0); + ifs.open(wname, std::ios_base::binary); + free(wname); +#else + ifs.open(name, std::ios_base::binary); +#endif +} + static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags) { const int channels = ibuf->channels; @@ -216,7 +245,13 @@ static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags header.channels().insert("Z", Channel(Imf::FLOAT)); FrameBuffer frameBuffer; - OutputFile *file = new OutputFile(name, header); + + /* manually create ofstream, so we can handle utf-8 filepaths on windows */ + std::ofstream std_ostream; + openexr_ofstream_open(std_ostream, name); + StdOFStream exr_ostream(std_ostream, name); + + OutputFile file(exr_ostream, header); /* we store first everything in half array */ RGBAZ *pixels = new RGBAZ[height * width]; @@ -281,9 +316,9 @@ static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags // printf("OpenEXR-save: Writing OpenEXR file of height %d.\n", height); - file->setFrameBuffer(frameBuffer); - file->writePixels(height); - delete file; + file.setFrameBuffer(frameBuffer); + file.writePixels(height); + delete[] pixels; } catch (const std::exception &exc) @@ -321,7 +356,14 @@ static int imb_save_openexr_float(struct ImBuf *ibuf, const char *name, int flag header.channels().insert("Z", Channel(Imf::FLOAT)); FrameBuffer frameBuffer; - OutputFile *file = new OutputFile(name, header); + + /* manually create ofstream, so we can handle utf-8 filepaths on windows */ + std::ofstream std_ostream; + openexr_ofstream_open(std_ostream, name); + StdOFStream exr_ostream(std_ostream, name); + + OutputFile file(exr_ostream, header); + int xstride = sizeof(float) * channels; int ystride = -xstride * width; float *rect[4] = {NULL, NULL, NULL, NULL}; @@ -340,9 +382,8 @@ static int imb_save_openexr_float(struct ImBuf *ibuf, const char *name, int flag if (is_zbuf) frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *) (ibuf->zbuf_float + (height - 1) * width), sizeof(float), sizeof(float) * -width)); - file->setFrameBuffer(frameBuffer); - file->writePixels(height); - delete file; + file.setFrameBuffer(frameBuffer); + file.writePixels(height); } catch (const std::exception &exc) { @@ -391,9 +432,15 @@ static ListBase exrhandles = {NULL, NULL}; typedef struct ExrHandle { struct ExrHandle *next, *prev; + std::ifstream *std_istream; + StdIFStream *exr_istream; InputFile *ifile; + + std::ofstream *std_ostream; + StdOFStream *exr_ostream; TiledOutputFile *tofile; OutputFile *ofile; + int tilex, tiley; int width, height; int mipmap; @@ -486,12 +533,24 @@ int IMB_exr_begin_write(void *handle, const char *filename, int width, int heigh header.insert("BlenderMultiChannel", StringAttribute("Blender V2.55.1 and newer")); /* avoid crash/abort when we don't have permission to write here */ + /* manually create ofstream, so we can handle utf-8 filepaths on windows */ try { - data->ofile = new OutputFile(filename, header); + data->std_ostream = new std::ofstream(); + openexr_ofstream_open(*(data->std_ostream), filename); + + data->exr_ostream = new StdOFStream(*(data->std_ostream), filename); + data->ofile = new OutputFile(*(data->exr_ostream), header); } catch (const std::exception &exc) { std::cerr << "IMB_exr_begin_write: ERROR: " << exc.what() << std::endl; + + delete data->ofile; + delete data->exr_ostream; + delete data->std_ostream; + data->ofile = NULL; + data->exr_ostream = NULL; + data->std_ostream = NULL; } return (data->ofile != NULL); @@ -518,7 +577,24 @@ void IMB_exrtile_begin_write(void *handle, const char *filename, int mipmap, int header.insert("BlenderMultiChannel", StringAttribute("Blender V2.43")); - data->tofile = new TiledOutputFile(filename, header); + /* avoid crash/abort when we don't have permission to write here */ + /* manually create ofstream, so we can handle utf-8 filepaths on windows */ + try { + data->std_ostream = new std::ofstream(); + openexr_ofstream_open(*(data->std_ostream), filename); + + data->exr_ostream = new StdOFStream(*(data->std_ostream), filename); + data->tofile = new TiledOutputFile(*(data->exr_ostream), header); + } + catch (const std::exception &exc) { + delete data->tofile; + delete data->exr_ostream; + delete data->std_ostream; + + data->tofile = NULL; + data->exr_ostream = NULL; + data->std_ostream = NULL; + } } /* read from file */ @@ -527,7 +603,25 @@ int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *heig ExrHandle *data = (ExrHandle *)handle; if (BLI_exists(filename) && BLI_file_size(filename) > 32) { /* 32 is arbitrary, but zero length files crashes exr */ - data->ifile = new InputFile(filename); + /* avoid crash/abort when we don't have permission to write here */ + /* manually create ofstream, so we can handle utf-8 filepaths on windows */ + try { + data->std_istream = new std::ifstream(); + openexr_ifstream_open(*(data->std_istream), filename); + + data->exr_istream = new StdIFStream(*(data->std_istream), filename); + data->ifile = new InputFile(*(data->exr_istream)); + } + catch (const std::exception &exc) { + delete data->ifile; + delete data->exr_istream; + delete data->std_istream; + + data->ifile = NULL; + data->exr_istream = NULL; + data->std_istream = NULL; + } + if (data->ifile) { Box2i dw = data->ifile->header().dataWindow(); data->width = *width = dw.max.x - dw.min.x + 1; @@ -696,16 +790,23 @@ void IMB_exr_close(void *handle) ExrLayer *lay; ExrPass *pass; - if (data->ifile) - delete data->ifile; - else if (data->ofile) - delete data->ofile; - else if (data->tofile) - delete data->tofile; + delete data->ifile; + delete data->exr_istream; + delete data->std_istream; + + delete data->ofile; + delete data->tofile; + delete data->exr_ostream; + delete data->std_ostream; data->ifile = NULL; + data->exr_istream = NULL; + data->std_istream = NULL; + data->ofile = NULL; data->tofile = NULL; + data->exr_ostream = NULL; + data->std_ostream = NULL; BLI_freelistN(&data->channels); |