Browse Source

Added image uri to MemoryImage when loading models with a custom context.

vpenades 7 months ago
parent
commit
5c4bd9643a

+ 5 - 0
src/SharpGLTF.Core/Memory/MemoryImage.cs

@@ -224,11 +224,16 @@ namespace SharpGLTF.Memory
         /// <para><b>⚠️ DO NOT USE AS AN OBJECT ID ⚠️</b> see remarks.</para>
         /// <para><b>⚠️ DO NOT USE AS AN OBJECT ID ⚠️</b> see remarks.</para>
         /// </summary>
         /// </summary>
         /// <remarks>
         /// <remarks>
+        /// <para>
         /// Not all images are expected to have a source path.<br/>
         /// Not all images are expected to have a source path.<br/>
         /// Specifically images embedded in a GLB file or encoded with BASE64
         /// Specifically images embedded in a GLB file or encoded with BASE64
         /// will not have any source path at all.<br/>
         /// will not have any source path at all.<br/>
         /// So if your code depends on images having a path, it might crash
         /// So if your code depends on images having a path, it might crash
         /// on gltf files with embedded images.
         /// on gltf files with embedded images.
+        /// </para>
+        /// <para>
+        /// If SourcePath has a value, it may be relative or absolute depending on the read context.
+        /// </para>
         /// </remarks>
         /// </remarks>
         public string SourcePath => _SourcePathHint;
         public string SourcePath => _SourcePathHint;
 
 

+ 1 - 1
src/SharpGLTF.Core/Schema2/Serialization.ReadSettings.cs

@@ -131,7 +131,7 @@ namespace SharpGLTF.Schema2
                 filePath = finfo.Name;
                 filePath = finfo.Name;
             }
             }
 
 
-            // at this point, filePath must be a path "relative to context"            
+            System.Diagnostics.Debug.Assert(Uri.TryCreate(filePath, UriKind.Relative, out _), "at this point, filePath must be a path relative to 'context'");
 
 
             return context.ReadSchema2(filePath);
             return context.ReadSchema2(filePath);
         }
         }

+ 1 - 1
src/SharpGLTF.Core/Schema2/gltf.Images.cs

@@ -167,7 +167,7 @@ namespace SharpGLTF.Schema2
                 // full path could not be resolved, use direct load instead.
                 // full path could not be resolved, use direct load instead.
                 else
                 else
                 {
                 {
-                    _SatelliteContent = context.ReadAllBytesToEnd(_uri);
+                    _SatelliteContent = new SharpGLTF.Memory.MemoryImage(context.ReadAllBytesToEnd(_uri), _uri);
                 }
                 }
             }
             }
 
 

+ 103 - 0
tests/SharpGLTF.Core.Tests/Schema2/LoadAndSave/ReadContextTests.cs

@@ -0,0 +1,103 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using NUnit.Framework;
+
+using SharpGLTF.Memory;
+
+namespace SharpGLTF.Schema2.LoadAndSave
+{
+    [AttachmentPathFormat("*/TestResults/ReadContextTests/?", true)]
+    internal class ReadContextTests
+    {
+        [Test]
+        public void TestLoadWithReadContext()
+        {
+            var modelPath = ResourceInfo.From("SpecialCases/RelativePaths.gltf");
+
+            var baseDirectory = modelPath.File.Directory;
+
+            ArraySegment<byte> _fileReader(string assetName)
+            {
+                assetName = Uri.UnescapeDataString(assetName);
+
+                var filePath = System.IO.Path.Combine(baseDirectory.FullName, assetName);
+                var finfo = new System.IO.FileInfo(filePath);
+
+                if (finfo.Exists)
+                {
+                    var data = System.IO.File.ReadAllBytes(filePath);
+
+                    return new ArraySegment<byte>(data);
+                }
+
+                throw new System.IO.FileNotFoundException(filePath);
+            }
+
+            var context = ReadContext.Create(_fileReader);
+
+            var model = ModelRoot.Load("RelativePaths.gltf", context);
+        }
+
+
+        [Test]
+        public void TestLoadWithReadContextAndTextureLoadSkip()
+        {
+            var modelPath = ResourceInfo.From("SpecialCases/RelativePaths.gltf");
+
+            var baseDirectory = modelPath.File.Directory;
+
+            // we store the uris for the tests at the end.
+            var imageUriCache = new HashSet<string>();
+
+            // this is a very tiny, placeholder PNG image to be used as replacement
+            // of the actual image. This ensures a valid image is passed to the model for
+            // the tests to pass.
+            var placeHolderImage = new ArraySegment<byte>(MemoryImage.DefaultPngImage);
+
+            ArraySegment<byte> _fileReader(string assetName)
+            {
+                assetName = Uri.UnescapeDataString(assetName);
+
+                var filePath = System.IO.Path.Combine(baseDirectory.FullName, assetName);
+                var finfo = new System.IO.FileInfo(filePath);
+
+                // skip image loading by replacing it with a tiny placeholder
+                if (finfo.Extension == ".jpg" || finfo.Extension == ".png")
+                {
+                    imageUriCache.Add(assetName);
+                    return placeHolderImage;
+                }
+
+                if (finfo.Exists)
+                {
+                    var data = System.IO.File.ReadAllBytes(filePath);
+
+                    return new ArraySegment<byte>(data);
+                }                
+
+                throw new System.IO.FileNotFoundException(filePath);
+            }
+
+            // load model and ensure the placeholder images contain proper paths
+
+            var context = ReadContext.Create(_fileReader);            
+
+            var model = ModelRoot.Load("RelativePaths.gltf", context);            
+
+            foreach(var img in model.LogicalImages)
+            {
+                var bitmap = img.Content; // Content is a MemoryImage object that countains a bitmap SourcePath.
+
+                Assert.That(bitmap.SourcePath, Is.Not.Null);
+
+                var srcPath = Uri.UnescapeDataString(bitmap.SourcePath);
+
+                Assert.That(imageUriCache.Contains(srcPath));
+            }
+        }
+    }
+}