Skip to content

Commit 5c4bd96

Browse files
committed
Added image uri to MemoryImage when loading models with a custom context.
1 parent 1211b5d commit 5c4bd96

File tree

4 files changed

+110
-2
lines changed

4 files changed

+110
-2
lines changed

src/SharpGLTF.Core/Memory/MemoryImage.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,11 +224,16 @@ public static bool AreEqual(MemoryImage a, MemoryImage b)
224224
/// <para><b>⚠️ DO NOT USE AS AN OBJECT ID ⚠️</b> see remarks.</para>
225225
/// </summary>
226226
/// <remarks>
227+
/// <para>
227228
/// Not all images are expected to have a source path.<br/>
228229
/// Specifically images embedded in a GLB file or encoded with BASE64
229230
/// will not have any source path at all.<br/>
230231
/// So if your code depends on images having a path, it might crash
231232
/// on gltf files with embedded images.
233+
/// </para>
234+
/// <para>
235+
/// If SourcePath has a value, it may be relative or absolute depending on the read context.
236+
/// </para>
232237
/// </remarks>
233238
public string SourcePath => _SourcePathHint;
234239

src/SharpGLTF.Core/Schema2/Serialization.ReadSettings.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ public static MODEL Load(string filePath, ReadSettings settings = null)
131131
filePath = finfo.Name;
132132
}
133133

134-
// at this point, filePath must be a path "relative to context"
134+
System.Diagnostics.Debug.Assert(Uri.TryCreate(filePath, UriKind.Relative, out _), "at this point, filePath must be a path relative to 'context'");
135135

136136
return context.ReadSchema2(filePath);
137137
}

src/SharpGLTF.Core/Schema2/gltf.Images.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ internal void _ResolveUri(ReadContext context)
167167
// full path could not be resolved, use direct load instead.
168168
else
169169
{
170-
_SatelliteContent = context.ReadAllBytesToEnd(_uri);
170+
_SatelliteContent = new SharpGLTF.Memory.MemoryImage(context.ReadAllBytesToEnd(_uri), _uri);
171171
}
172172
}
173173

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
using NUnit.Framework;
8+
9+
using SharpGLTF.Memory;
10+
11+
namespace SharpGLTF.Schema2.LoadAndSave
12+
{
13+
[AttachmentPathFormat("*/TestResults/ReadContextTests/?", true)]
14+
internal class ReadContextTests
15+
{
16+
[Test]
17+
public void TestLoadWithReadContext()
18+
{
19+
var modelPath = ResourceInfo.From("SpecialCases/RelativePaths.gltf");
20+
21+
var baseDirectory = modelPath.File.Directory;
22+
23+
ArraySegment<byte> _fileReader(string assetName)
24+
{
25+
assetName = Uri.UnescapeDataString(assetName);
26+
27+
var filePath = System.IO.Path.Combine(baseDirectory.FullName, assetName);
28+
var finfo = new System.IO.FileInfo(filePath);
29+
30+
if (finfo.Exists)
31+
{
32+
var data = System.IO.File.ReadAllBytes(filePath);
33+
34+
return new ArraySegment<byte>(data);
35+
}
36+
37+
throw new System.IO.FileNotFoundException(filePath);
38+
}
39+
40+
var context = ReadContext.Create(_fileReader);
41+
42+
var model = ModelRoot.Load("RelativePaths.gltf", context);
43+
}
44+
45+
46+
[Test]
47+
public void TestLoadWithReadContextAndTextureLoadSkip()
48+
{
49+
var modelPath = ResourceInfo.From("SpecialCases/RelativePaths.gltf");
50+
51+
var baseDirectory = modelPath.File.Directory;
52+
53+
// we store the uris for the tests at the end.
54+
var imageUriCache = new HashSet<string>();
55+
56+
// this is a very tiny, placeholder PNG image to be used as replacement
57+
// of the actual image. This ensures a valid image is passed to the model for
58+
// the tests to pass.
59+
var placeHolderImage = new ArraySegment<byte>(MemoryImage.DefaultPngImage);
60+
61+
ArraySegment<byte> _fileReader(string assetName)
62+
{
63+
assetName = Uri.UnescapeDataString(assetName);
64+
65+
var filePath = System.IO.Path.Combine(baseDirectory.FullName, assetName);
66+
var finfo = new System.IO.FileInfo(filePath);
67+
68+
// skip image loading by replacing it with a tiny placeholder
69+
if (finfo.Extension == ".jpg" || finfo.Extension == ".png")
70+
{
71+
imageUriCache.Add(assetName);
72+
return placeHolderImage;
73+
}
74+
75+
if (finfo.Exists)
76+
{
77+
var data = System.IO.File.ReadAllBytes(filePath);
78+
79+
return new ArraySegment<byte>(data);
80+
}
81+
82+
throw new System.IO.FileNotFoundException(filePath);
83+
}
84+
85+
// load model and ensure the placeholder images contain proper paths
86+
87+
var context = ReadContext.Create(_fileReader);
88+
89+
var model = ModelRoot.Load("RelativePaths.gltf", context);
90+
91+
foreach(var img in model.LogicalImages)
92+
{
93+
var bitmap = img.Content; // Content is a MemoryImage object that countains a bitmap SourcePath.
94+
95+
Assert.That(bitmap.SourcePath, Is.Not.Null);
96+
97+
var srcPath = Uri.UnescapeDataString(bitmap.SourcePath);
98+
99+
Assert.That(imageUriCache.Contains(srcPath));
100+
}
101+
}
102+
}
103+
}

0 commit comments

Comments
 (0)