If a content image is the result of a blob. (in this case a binary file with embedded jpg's or png's).
Texture will fail.
If texture.needUpdate is set, warning is triggered that the image isn't complete but somehow allows the texture to be rendered properly.
Tried as a work around, to wait a short delay for the images to be complete and then declare the texture with the image: fails.
Same for CubeTexture, except no warning is triggered and always fails, even if needUpdate is set when all images are complete or setting images array with all images.complete true.
Note that if added to the html page, the images/blobs are displayed, all displayed in browser resources list as well. And when complete is true, the correct width/height are also available.
Example of the blob constructs for a jpg (imType:jepg)
var imLen = this.readU32();
var imBuffer = new Uint8Array(imLen);
var i = 0;
var buff = this.bytes.buffer;
while(i<imLen){
imBuffer[i] = this.readU8();
i++;
}
var blob = new Blob( [ imBuffer ], { type: "image/"+imType } );
var url = URL.createObjectURL(blob);
var image = new Image();
image.crossOrigin = "Anonymous";
image.src = url;
var texture = new THREE.Texture();
texture.format = (imType == "jpeg") ? THREE.RGBFormat : THREE.RGBAFormat;
texture.image = image;
texture.needsUpdate = true; // will trigger warning because image not complete, but display the map ok.
return texture;
The threejs code assumes image.width/height are other than 0, while image constructor params width & height are updated once the blob sets the image flag complete to true.
I've been able to use Blob URLs successfully through the TextureLoader interface:
var url = URL.createObjectURL( blob );
var loader = new THREE.TextureLoader();
loader.load( url, function ( texture ) {
URL.revokeObjectURL( url );
console.log(texture);
});
EDIT: Full example.
THREE.DataTexture usage may also be appropriate here if you already have the bytes.
Meanwhile refactored my parser with a better delay/check complete flag for cube sources and it works.
Tried the blob urls to feed the loader as @donmccurdy suggested, feels bit silly to "reload" data you already have, but as it's removing the need of an extra check/delay in my code as the onLoaded is triggered only when the img are complete, went for that one and removed my previous check.
@mrdoob
var texture = new THREE.DataTexture( data, width, height, THREE.RGBFormat );
yes that's handy when the width and height of the image are known. In my case, no size in file, just png's and jpg's buffers. The w/h of the image are set once the blob is complete. I would also still need to parse the headers of the streams to id jepg (FF D8) or png/transparent to set RGB or RGBAFormat.
Also as there is no DataCubeTexture,(this bins also store envMaps, skyboxes etc..) I'd be forced to do more or less what I did first.
All with all, if three would check if img.complete and handle a delay if img isn't null (vs just a warning and set size of 0 x 0 and upload) the engine would then build valid textures with no prob using
var text = new THREE.Texture();
text.image = myImageFromBLOBNotPerseComplete;
mat.map = text;
which would remove the need to declare a loader that you actually don't need...
Anyway, glad that it works for now... thx both of you!
Most helpful comment
I've been able to use Blob URLs successfully through the TextureLoader interface:
EDIT: Full example.