vpenades / SharpGLTF

glTF reader and writer for .NET Standard
MIT License
470 stars 75 forks source link

Incorrect image buffer data #17

Closed hexuallyactive closed 5 years ago

hexuallyactive commented 5 years ago

There's a difference between Image.GetImageContent() between gltf and glb. When loading a glb, the entire buffer is returned

vpenades commented 5 years ago

GetImageContent() returns an ArraySegment<Byte>

ArraySegment<Byte> usually represents a slice over a larger Byte[] array. If you inspect its properties you'll find:

When you load a glTF, images are loaded separately, so in general, ArraySegment is a segment that covers the entire underlaying image array, so the .Offset will be zero, and .Count will be the size of the array.

But when loading a GLB, the images are contained in the large binary array of the GLB, so you must take into account .Offset and .Count to get the segment of the array that is the image. This has the advantage that avoids making a very slow copy of the data.

An example of accessing the ArraySegment would be this:

ArraySegment<Byte> segment = new ...;
for( int i = segment.Offset; i < segment.Count; ++i )
{
    Byte value = segment.Array[ segment.Offset + i];
}

You could see Arrays as glTF buffers, and ArraySegments as glTF BufferViews, understanding how ArraySegments work is crucial because SharpGLTF uses them extensively to acccess buffer segments very fast.

But if you're in a hurry, you can use LinQ and just do: ArraySegment<Byte>.ToArray() or even GetImageContent().ToArray() which will create a defensive copy of the segment and return the exact array you need.

hexuallyactive commented 5 years ago

Ah, I see - makes sense now - thank you!