changeset 28473:04ee5e8694cb

__magick_read__.cc: Correctly read images from non-ASCII paths on Windows (bug #58493). * libinterp/corefcn/__magick_read__.cc (read_file): Add new function overload to read the image file content into a blob. (F__magick_ping__): On Windows file systems, read image file into blob.
author Markus Mützel <markus.muetzel@gmx.de>
date Sun, 14 Jun 2020 13:02:59 +0200
parents a40e3c3e17fa
children 4539c931734a
files libinterp/corefcn/__magick_read__.cc
diffstat 1 files changed, 62 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/__magick_read__.cc	Sun Jun 14 12:17:10 2020 +0200
+++ b/libinterp/corefcn/__magick_read__.cc	Sun Jun 14 13:02:59 2020 +0200
@@ -28,6 +28,7 @@
 #endif
 
 #include "file-stat.h"
+#include "lo-sysdep.h"
 #include "oct-env.h"
 #include "oct-time.h"
 
@@ -750,13 +751,58 @@
   return retval;
 }
 
+// Read file content into blob.
+static Magick::Blob
+read_file (const std::string& filename)
+{
+  octave::sys::file_stat fs (filename);
+
+  if (! fs)
+    error ("no such file, '%s'", filename.c_str ());
+
+  size_t sz = fs.size ();
+
+  std::ifstream file = octave::sys::ifstream (filename.c_str (),
+                                              std::ios::in | std::ios::binary);
+
+  std::string fstr (sz+1, 0);
+  if (file)
+    {
+      file.read (&fstr[0], sz+1);
+
+      if (! file.eof ())
+        error ("error reading file %s", filename.c_str ());
+    }
+
+  Magick::Blob blob;
+  try
+    {
+      // Convert to blob
+      blob = Magick::Blob (fstr.c_str (), fstr.size ());
+    }
+  catch (Magick::Warning& w)
+    {
+      warning ("Magick++ warning: %s", w.what ());
+    }
+  catch (Magick::Exception& e)
+    {
+      error ("Magick++ exception: %s", e.what ());
+    }
+
+  return blob;
+}
+
 // Read a file into vector of image objects.
 void static
 read_file (const std::string& filename, std::vector<Magick::Image>& imvec)
 {
+  // Read file content into blob
+  Magick::Blob blob = read_file (filename);
+
   try
     {
-      Magick::readImages (&imvec, filename);
+      // Create images from blob
+      Magick::readImages (&imvec, blob);
     }
   catch (Magick::Warning& w)
     {
@@ -1687,10 +1733,25 @@
   Magick::Image img;
   img.subImage (idx); // start ping from this image (in case of multi-page)
   img.subRange (1);   // ping only one of them
+
+#  if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
+  // Magick++ doesn't handle UTF-8 encoded file names on Windows.
+  // To prevent an error in this case, read the file content into a blob and
+  // pass the blob to Magick::Image::ping. This is less efficient than passing
+  // the file name to Magick::Image::ping because this requires to read the
+  // entire file from the disk. So, do this on affected file systems only.
+  Magick::Blob blob = read_file (filename);
+
+  try
+    {
+      img.ping (blob);
+    }
+#  else
   try
     {
       img.ping (filename);
     }
+#  endif
   catch (Magick::Warning& w)
     {
       warning ("Magick++ warning: %s", w.what ());