What is the fastest and most efficient way to read a Uint8Array into a THREE.Texture?

Let’s say I have a Uint8Array that represents a 1,024x1,204 png image.

I am currently doing this for reading it into a THREE.Texture object:

const textureLoader = new three.TextureLoader();
const pngBytes = getPngBytes(); // Uint8Array
const blob new Blob([pngBytes], {type: `image/png`});
const url = URL.createObjectURL(src);
let texture;
try {
    texture = await textureLoader.loadAsync(url);
} finally {
    URL.revokeObjectURL(url);
}
// do something with texture...

Am I doing it the right way already? Or is there a more efficient way to do this?

If you have an Image or < img > or a Canvas or < canvas >, you don’t need to do this… you can just do:

texture = new THREE.CanvasTexture(yourCanvas)

or

texture = new THREE.Texture( yourImage );

otherwise if you really only have uint8array (rgba format), you need to know the width and height, and:

texture = new THREE.DataTexure( rgbaData, width, height, THREE.RGBAFormat )

Is all you need.

If your data isn’t RGBA, (for instance rgb.. you’ll have to expand it to rgba since rgb textures are no longer supported iirc. so just put 255 in the alpha channel when you expand it.)
like:

let rgbaData = new Uint8Array( rgbData.length*4/3 );
for(let i=0,j=0;i<rgbData.length;i+=3){
  rgbaData[j++]=rgbData[i];
  rgbaData[j++]=rgbData[i+1];
  rgbaData[j++]=rgbData[i+2];
  rgbaData[j++]=255;
}
texture = new THREE.DataTexure( rgbaData, width, height, THREE.RGBAFormat )

I am assuming you know the width and height. If you don’t, then you’ll need to figure out how to get it from the original source.

3 Likes

Thanks! I glanced at DataTexture but wasn’t quite sure how to use it.

I presume however that if I use DataTexture, I can’t use compressed images like png, jpeg, gif, etc.? This would be a problem for me, as my application reads and parses a big byte array blob that contains a bunch of png images packed together, and not raw RGBA.

Ohhh ok. That’s a bit different. For that, you’ll have to decode them into Images first, then use the:
new Texture(image) approach on each resulting image in the sequence.

Unless.. you are trying to load this for some kind of 3d slicing visualization tomography..(and they’re all the same size). in which case you may need a texture array or a 3d texture