[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [50176] trunk/blender/source/blender/imbuf /intern/openexr: Fix second part #32377: saving/ loading exr files to file paths with non-ascii

Brecht Van Lommel brechtvanlommel at pandora.be
Fri Aug 24 14:10:36 CEST 2012


Revision: 50176
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=50176
Author:   blendix
Date:     2012-08-24 12:10:35 +0000 (Fri, 24 Aug 2012)
Log Message:
-----------
Fix second part #32377: saving/loading exr files to file paths with non-ascii
characters should now work on Windows.

Modified Paths:
--------------
    trunk/blender/source/blender/imbuf/intern/openexr/CMakeLists.txt
    trunk/blender/source/blender/imbuf/intern/openexr/SConscript
    trunk/blender/source/blender/imbuf/intern/openexr/openexr_api.cpp

Modified: trunk/blender/source/blender/imbuf/intern/openexr/CMakeLists.txt
===================================================================
--- trunk/blender/source/blender/imbuf/intern/openexr/CMakeLists.txt	2012-08-24 11:02:01 UTC (rev 50175)
+++ trunk/blender/source/blender/imbuf/intern/openexr/CMakeLists.txt	2012-08-24 12:10:35 UTC (rev 50176)
@@ -31,6 +31,7 @@
 	../../../blenlib
 	../../../makesdna
 	../../../../../intern/guardedalloc
+	../../../../../intern/utfconv
 )
 
 set(INC_SYS

Modified: trunk/blender/source/blender/imbuf/intern/openexr/SConscript
===================================================================
--- trunk/blender/source/blender/imbuf/intern/openexr/SConscript	2012-08-24 11:02:01 UTC (rev 50175)
+++ trunk/blender/source/blender/imbuf/intern/openexr/SConscript	2012-08-24 12:10:35 UTC (rev 50176)
@@ -10,7 +10,9 @@
     '../../../blenlib',
     'intern/include',
     '#/intern/guardedalloc',
-    '../../../makesdna']
+    '../../../makesdna',
+    '#/intern/utfconv']
+
 incs += Split(env['BF_OPENEXR_INC'])
 
 defs = ['WITH_OPENEXR']

Modified: trunk/blender/source/blender/imbuf/intern/openexr/openexr_api.cpp
===================================================================
--- trunk/blender/source/blender/imbuf/intern/openexr/openexr_api.cpp	2012-08-24 11:02:01 UTC (rev 50175)
+++ trunk/blender/source/blender/imbuf/intern/openexr/openexr_api.cpp	2012-08-24 12:10:35 UTC (rev 50176)
@@ -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 @@
 #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 @@
 #include <ImfCompression.h>
 #include <ImfCompressionAttribute.h>
 #include <ImfStringAttribute.h>
+#include <ImfStdIO.h>
 #endif
 
 using namespace Imf;
@@ -192,6 +199,28 @@
 		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,8 +245,14 @@
 			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];
 		RGBAZ *to = pixels;
@@ -281,9 +316,9 @@
 
 //		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 @@
 			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 @@
 		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 @@
 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 @@
 	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 @@
 
 	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 @@
 	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 @@
 	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);
 




More information about the Bf-blender-cvs mailing list